/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef AAPT_PROGUARD_RULES_H
#define AAPT_PROGUARD_RULES_H

#include <map>
#include <ostream>
#include <set>
#include <string>

#include "androidfw/StringPiece.h"

#include "Resource.h"
#include "ResourceTable.h"
#include "Source.h"
#include "ValueVisitor.h"
#include "io/Io.h"
#include "process/IResourceTableConsumer.h"
#include "xml/XmlDom.h"

namespace aapt {
namespace proguard {

struct UsageLocation {
  ResourceName name;
  Source source;
};

class KeepSet {
 public:
  KeepSet() = default;

  explicit KeepSet(bool conditional_keep_rules) : conditional_keep_rules_(conditional_keep_rules) {
  }

  inline void AddManifestClass(const UsageLocation& file, const std::string& class_name) {
    manifest_class_set_[class_name].insert(file);
  }

  inline void AddConditionalClass(const UsageLocation& file, const std::string& class_name) {
    conditional_class_set_[class_name].insert(file);
  }

  inline void AddMethod(const UsageLocation& file, const std::string& method_name) {
    method_set_[method_name].insert(file);
  }

  inline void AddReference(const UsageLocation& file, const ResourceName& resource_name) {
    reference_set_[resource_name].insert(file);
  }

 private:
  friend void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out);

  friend bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
                               std::set<UsageLocation>* locations);

  bool conditional_keep_rules_ = false;
  std::map<std::string, std::set<UsageLocation>> manifest_class_set_;
  std::map<std::string, std::set<UsageLocation>> method_set_;
  std::map<std::string, std::set<UsageLocation>> conditional_class_set_;
  std::map<ResourceName, std::set<UsageLocation>> reference_set_;
};

bool CollectProguardRulesForManifest(xml::XmlResource* res, KeepSet* keep_set,
                                     bool main_dex_only = false);

bool CollectProguardRules(xml::XmlResource* res, KeepSet* keep_set);

bool CollectResourceReferences(IAaptContext* context, ResourceTable* table, KeepSet* keep_set);

void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out);

bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
                      std::set<UsageLocation>* locations);

//
// UsageLocation implementation.
//

inline bool operator==(const UsageLocation& lhs, const UsageLocation& rhs) {
  return lhs.name == rhs.name;
}

inline int operator<(const UsageLocation& lhs, const UsageLocation& rhs) {
  return lhs.name.compare(rhs.name);
}

}  // namespace proguard
}  // namespace aapt

#endif  // AAPT_PROGUARD_RULES_H
