/*
 * Copyright (C) 2018, 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.
 */

#include "aidl_typenames.h"
#include "aidl_language.h"
#include "logging.h"

#include <android-base/strings.h>

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

using android::base::Split;

using std::make_pair;
using std::map;
using std::pair;
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace android {
namespace aidl {

// The built-in AIDL types..
static const set<string> kBuiltinTypes = {
    "void", "boolean", "byte",           "char",         "int",
    "long", "float",   "double",         "String",       "List",
    "Map",  "IBinder", "FileDescriptor", "CharSequence", "ParcelFileDescriptor"};

static const set<string> kPrimitiveTypes = {"void", "boolean", "byte",  "char",
                                            "int",  "long",    "float", "double"};

// Note: these types may look wrong because they look like Java
// types, but they have long been supported from the time when Java
// was the only target language of this compiler. They are added here for
// backwards compatibility, but we internally treat them as List and Map,
// respectively.
static const map<string, string> kJavaLikeTypeToAidlType = {
    {"java.util.List", "List"},
    {"java.util.Map", "Map"},
    {"android.os.ParcelFileDescriptor", "ParcelFileDescriptor"},
};

// Package name and type name can't be one of these as they are keywords
// in Java and C++. Using these names will eventually cause compilation error,
// so checking this here is not a must have, but early detection of errors
// is always better.
static const set<string> kInvalidNames = {
    "break",  "case",   "catch", "char",     "class",  "continue", "default",
    "do",     "double", "else",  "enum",     "false",  "float",    "for",
    "goto",   "if",     "int",   "long",     "new",    "private",  "protected",
    "public", "return", "short", "static",   "switch", "this",     "throw",
    "true",   "try",    "void",  "volatile", "while"};

static bool IsValidName(const string& name) {
  vector<string> pieces = Split(name, ".");
  for (const auto& piece : pieces) {
    if (kInvalidNames.find(piece) != kInvalidNames.end()) {
      return false;
    }
  }
  return true;
}

bool AidlTypenames::IsIgnorableImport(const string& import) const {
  static set<string> ignore_import = {"android.os.IInterface",   "android.os.IBinder",
                                      "android.os.Parcelable",   "android.os.Parcel",
                                      "android.content.Context", "java.lang.String"};
  // these known built-in types don't need to be imported
  const bool in_ignore_import = ignore_import.find(import) != ignore_import.end();
  // an already defined type doesn't need to be imported again unless it is from
  // the preprocessed file
  auto ret = TryGetDefinedTypeImpl(import);
  const bool defined_type_not_from_preprocessed = ret.type != nullptr && !ret.from_preprocessed;
  return in_ignore_import || defined_type_not_from_preprocessed;
}

bool AidlTypenames::AddDefinedType(unique_ptr<AidlDefinedType> type) {
  const string name = type->GetCanonicalName();
  if (defined_types_.find(name) != defined_types_.end()) {
    return false;
  }
  if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
    return false;
  }
  defined_types_.emplace(name, std::move(type));
  return true;
}

bool AidlTypenames::AddPreprocessedType(unique_ptr<AidlDefinedType> type) {
  const string name = type->GetCanonicalName();
  if (preprocessed_types_.find(name) != preprocessed_types_.end()) {
    return false;
  }
  if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
    return false;
  }
  preprocessed_types_.insert(make_pair(name, std::move(type)));
  return true;
}

bool AidlTypenames::IsBuiltinTypename(const string& type_name) {
  return kBuiltinTypes.find(type_name) != kBuiltinTypes.end() ||
      kJavaLikeTypeToAidlType.find(type_name) != kJavaLikeTypeToAidlType.end();
}

bool AidlTypenames::IsPrimitiveTypename(const string& type_name) {
  return kPrimitiveTypes.find(type_name) != kPrimitiveTypes.end();
}

const AidlDefinedType* AidlTypenames::TryGetDefinedType(const string& type_name) const {
  return TryGetDefinedTypeImpl(type_name).type;
}

AidlTypenames::DefinedImplResult AidlTypenames::TryGetDefinedTypeImpl(
    const string& type_name) const {
  // Do the exact match first.
  auto found_def = defined_types_.find(type_name);
  if (found_def != defined_types_.end()) {
    return DefinedImplResult(found_def->second.get(), false);
  }

  auto found_prep = preprocessed_types_.find(type_name);
  if (found_prep != preprocessed_types_.end()) {
    return DefinedImplResult(found_prep->second.get(), true);
  }

  // Then match with the class name. Defined types has higher priority than
  // types from the preprocessed file.
  for (auto it = defined_types_.begin(); it != defined_types_.end(); it++) {
    if (it->second->GetName() == type_name) {
      return DefinedImplResult(it->second.get(), false);
    }
  }

  for (auto it = preprocessed_types_.begin(); it != preprocessed_types_.end(); it++) {
    if (it->second->GetName() == type_name) {
      return DefinedImplResult(it->second.get(), true);
    }
  }

  return DefinedImplResult(nullptr, false);
}

pair<string, bool> AidlTypenames::ResolveTypename(const string& type_name) const {
  if (IsBuiltinTypename(type_name)) {
    auto found = kJavaLikeTypeToAidlType.find(type_name);
    if (found != kJavaLikeTypeToAidlType.end()) {
      return make_pair(found->second, true);
    }
    return make_pair(type_name, true);
  }
  const AidlDefinedType* defined_type = TryGetDefinedType(type_name);
  if (defined_type != nullptr) {
    return make_pair(defined_type->GetCanonicalName(), true);
  } else {
    return make_pair(type_name, false);
  }
}

// Only T[], List, Map, ParcelFileDescriptor and Parcelable can be an out parameter.
bool AidlTypenames::CanBeOutParameter(const AidlTypeSpecifier& type) const {
  const string& name = type.GetName();
  if (IsBuiltinTypename(name) || GetEnumDeclaration(type)) {
    return type.IsArray() || type.GetName() == "List" || type.GetName() == "Map" ||
           type.GetName() == "ParcelFileDescriptor";
  }
  const AidlDefinedType* t = TryGetDefinedType(type.GetName());
  CHECK(t != nullptr) << "Unrecognized type: '" << type.GetName() << "'";
  return t->AsParcelable() != nullptr;
}

const AidlEnumDeclaration* AidlTypenames::GetEnumDeclaration(const AidlTypeSpecifier& type) const {
  if (auto defined_type = TryGetDefinedType(type.GetName()); defined_type != nullptr) {
    if (auto enum_decl = defined_type->AsEnumDeclaration(); enum_decl != nullptr) {
      return enum_decl;
    }
  }
  return nullptr;
}

const AidlInterface* AidlTypenames::GetInterface(const AidlTypeSpecifier& type) const {
  if (auto defined_type = TryGetDefinedType(type.GetName()); defined_type != nullptr) {
    if (auto intf = defined_type->AsInterface(); intf != nullptr) {
      return intf;
    }
  }
  return nullptr;
}

void AidlTypenames::IterateTypes(const std::function<void(const AidlDefinedType&)>& body) const {
  for (const auto& kv : defined_types_) {
    body(*kv.second);
  }
  for (const auto& kv : preprocessed_types_) {
    body(*kv.second);
  }
}

void AidlTypenames::Reset() {
  defined_types_.clear();
  preprocessed_types_.clear();
}

}  // namespace aidl
}  // namespace android
