/*
 * Copyright (C) 2019 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 SRC_PROFILING_DEOBFUSCATOR_H_
#define SRC_PROFILING_DEOBFUSCATOR_H_

#include <functional>
#include <map>
#include <string>
#include <utility>
#include <vector>

namespace perfetto {
namespace profiling {

std::string FlattenClasses(
    const std::map<std::string, std::vector<std::string>>& m);

class ObfuscatedClass {
 public:
  explicit ObfuscatedClass(std::string d) : deobfuscated_name_(std::move(d)) {}
  ObfuscatedClass(
      std::string d,
      std::map<std::string, std::string> f,
      std::map<std::string, std::map<std::string, std::vector<std::string>>> m)
      : deobfuscated_name_(std::move(d)),
        deobfuscated_fields_(std::move(f)),
        deobfuscated_methods_(std::move(m)) {}

  const std::string& deobfuscated_name() const { return deobfuscated_name_; }

  const std::map<std::string, std::string>& deobfuscated_fields() const {
    return deobfuscated_fields_;
  }

  std::map<std::string, std::string> deobfuscated_methods() const {
    std::map<std::string, std::string> result;
    for (const auto& p : deobfuscated_methods_) {
      result.emplace(p.first, FlattenClasses(p.second));
    }
    return result;
  }

  bool redefined_methods() const { return redefined_methods_; }

  bool AddField(std::string obfuscated_name, std::string deobfuscated_name) {
    auto p = deobfuscated_fields_.emplace(std::move(obfuscated_name),
                                          deobfuscated_name);
    return p.second && p.first->second == deobfuscated_name;
  }

  void AddMethod(std::string obfuscated_name, std::string deobfuscated_name) {
    std::string cls = deobfuscated_name_;
    auto dot = deobfuscated_name.rfind('.');
    if (dot != std::string::npos) {
      cls = deobfuscated_name.substr(0, dot);
      deobfuscated_name = deobfuscated_name.substr(dot + 1);
    }
    auto& deobfuscated_names_for_cls =
        deobfuscated_methods_[std::move(obfuscated_name)][std::move(cls)];
    deobfuscated_names_for_cls.push_back(std::move(deobfuscated_name));
    if (deobfuscated_names_for_cls.size() > 1 ||
        deobfuscated_methods_.size() > 1) {
      redefined_methods_ = true;
    }
  }

 private:
  std::string deobfuscated_name_;
  std::map<std::string, std::string> deobfuscated_fields_;
  std::map<std::string, std::map<std::string, std::vector<std::string>>>
      deobfuscated_methods_;
  bool redefined_methods_ = false;
};

class ProguardParser {
 public:
  // A return value of false means this line failed to parse. This leaves the
  // parser in an undefined state and it should no longer be used.
  bool AddLine(std::string line);
  bool AddLines(std::string contents);

  std::map<std::string, ObfuscatedClass> ConsumeMapping() {
    return std::move(mapping_);
  }

 private:
  std::map<std::string, ObfuscatedClass> mapping_;
  ObfuscatedClass* current_class_ = nullptr;
};

struct ProguardMap {
  std::string package;
  std::string filename;
};

void MakeDeobfuscationPackets(
    const std::string& package_name,
    const std::map<std::string, profiling::ObfuscatedClass>& mapping,
    std::function<void(const std::string&)> callback);

std::vector<ProguardMap> GetPerfettoProguardMapPath();

bool ReadProguardMapsToDeobfuscationPackets(
    const std::vector<ProguardMap>& maps,
    std::function<void(std::string)> fn);

}  // namespace profiling
}  // namespace perfetto

#endif  // SRC_PROFILING_DEOBFUSCATOR_H_
