/*
 * 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.h"

#include <map>
#include <string>
#include <vector>

#include <android-base/result.h>
#include <android-base/strings.h>
#include <gtest/gtest.h>

#include "aidl_dumpapi.h"
#include "aidl_language.h"
#include "import_resolver.h"
#include "logging.h"
#include "options.h"

namespace android {
namespace aidl {

using android::base::Error;
using android::base::Result;
using android::base::StartsWith;
using std::map;
using std::set;
using std::string;
using std::vector;

struct DumpForEqualityVisitor : DumpVisitor {
  DumpForEqualityVisitor(CodeWriter& out) : DumpVisitor(out) {}

  void DumpConstantValue(const AidlTypeSpecifier&, const AidlConstantValue& c) {
    out << c.Literal();
  }
};

static std::string Dump(const AidlDefinedType& type) {
  string code;
  CodeWriterPtr out = CodeWriter::ForString(&code);
  DumpForEqualityVisitor visitor(*out);
  type.DispatchVisit(visitor);
  out->Close();
  return code;
}

// Uses each type's Dump() and GTest utility(EqHelper).
static bool CheckEquality(const AidlDefinedType& older, const AidlDefinedType& newer) {
  using testing::internal::EqHelper;
  auto older_file = older.GetLocation().GetFile();
  auto newer_file = newer.GetLocation().GetFile();
  auto result = EqHelper::Compare(older_file.data(), newer_file.data(), Dump(older), Dump(newer));
  if (!result) {
    AIDL_ERROR(newer) << result.failure_message();
  }
  return result;
}

static vector<string> get_strict_annotations(const AidlAnnotatable& node) {
  // This must be symmetrical (if you can add something, you must be able to
  // remove it). The reason is that we have no way of knowing which interface a
  // server serves and which interface a client serves (e.g. a callback
  // interface). Note that this is being overly lenient. It makes sense for
  // newer code to start accepting nullable things. However, here, we don't know
  // if the client of an interface or the server of an interface is newer.
  //
  // Here are two examples to demonstrate this:
  // - a new implementation might change so that it no longer returns null
  // values (remove @nullable)
  // - a new implementation might start accepting null values (add @nullable)
  static const set<AidlAnnotation::Type> kIgnoreAnnotations{
      AidlAnnotation::Type::NULLABLE,
      // @JavaDerive doesn't affect read/write
      AidlAnnotation::Type::JAVA_DERIVE,
      AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
      // @Backing for a enum type is checked by the enum checker
      AidlAnnotation::Type::BACKING,
      // @RustDerive doesn't affect read/write
      AidlAnnotation::Type::RUST_DERIVE,
      AidlAnnotation::Type::SUPPRESS_WARNINGS,
  };
  vector<string> annotations;
  for (const AidlAnnotation& annotation : node.GetAnnotations()) {
    if (kIgnoreAnnotations.find(annotation.GetType()) != kIgnoreAnnotations.end()) {
      continue;
    }
    auto annotation_string = annotation.ToString();
    // adding @Deprecated (with optional args) is okay
    if (StartsWith(annotation_string, "@JavaPassthrough(annotation=\"@Deprecated")) {
      continue;
    }
    annotations.push_back(annotation_string);
  }
  return annotations;
}

static bool have_compatible_annotations(const AidlAnnotatable& older,
                                        const AidlAnnotatable& newer) {
  vector<string> olderAnnotations = get_strict_annotations(older);
  vector<string> newerAnnotations = get_strict_annotations(newer);
  sort(olderAnnotations.begin(), olderAnnotations.end());
  sort(newerAnnotations.begin(), newerAnnotations.end());
  if (olderAnnotations != newerAnnotations) {
    const string from = older.ToString().empty() ? "(empty)" : older.ToString();
    const string to = newer.ToString().empty() ? "(empty)" : newer.ToString();
    AIDL_ERROR(newer) << "Changed annotations: " << from << " to " << to;
    return false;
  }
  return true;
}

static bool are_compatible_types(const AidlTypeSpecifier& older, const AidlTypeSpecifier& newer) {
  bool compatible = true;
  if (older.Signature() != newer.Signature()) {
    AIDL_ERROR(newer) << "Type changed: " << older.Signature() << " to " << newer.Signature()
                      << ".";
    compatible = false;
  }
  compatible &= have_compatible_annotations(older, newer);
  return compatible;
}

static bool are_compatible_constants(const AidlDefinedType& older, const AidlDefinedType& newer) {
  bool compatible = true;

  map<string, AidlConstantDeclaration*> new_constdecls;
  for (const auto& c : newer.GetConstantDeclarations()) {
    new_constdecls[c->GetName()] = &*c;
  }

  for (const auto& old_c : older.GetConstantDeclarations()) {
    const auto found = new_constdecls.find(old_c->GetName());
    if (found == new_constdecls.end()) {
      AIDL_ERROR(old_c) << "Removed constant declaration: " << older.GetCanonicalName() << "."
                        << old_c->GetName();
      compatible = false;
      continue;
    }

    const auto new_c = found->second;
    compatible &= are_compatible_types(old_c->GetType(), new_c->GetType());

    const string old_value = old_c->GetValue().Literal();
    const string new_value = new_c->GetValue().Literal();
    if (old_value != new_value) {
      AIDL_ERROR(newer) << "Changed constant value: " << older.GetCanonicalName() << "."
                        << old_c->GetName() << " from " << old_value << " to " << new_value << ".";
      compatible = false;
    }
  }
  return compatible;
}

static bool are_compatible_interfaces(const AidlInterface& older, const AidlInterface& newer) {
  bool compatible = true;

  map<string, AidlMethod*> new_methods;
  for (const auto& m : newer.AsInterface()->GetMethods()) {
    new_methods.emplace(m->Signature(), m.get());
  }

  for (const auto& old_m : older.AsInterface()->GetMethods()) {
    const auto found = new_methods.find(old_m->Signature());
    if (found == new_methods.end()) {
      AIDL_ERROR(old_m) << "Removed or changed method: " << older.GetCanonicalName() << "."
                        << old_m->Signature();
      compatible = false;
      continue;
    }

    // Compare IDs to detect method reordering. IDs are assigned by their
    // textual order, so if there is an ID mismatch, that means reordering
    // has happened.
    const auto new_m = found->second;

    if (old_m->IsOneway() != new_m->IsOneway()) {
      AIDL_ERROR(new_m) << "Oneway attribute " << (old_m->IsOneway() ? "removed" : "added") << ": "
                        << older.GetCanonicalName() << "." << old_m->Signature();
      compatible = false;
    }

    if (old_m->GetId() != new_m->GetId()) {
      AIDL_ERROR(new_m) << "Transaction ID changed: " << older.GetCanonicalName() << "."
                        << old_m->Signature() << " is changed from " << old_m->GetId() << " to "
                        << new_m->GetId() << ".";
      compatible = false;
    }

    compatible &= are_compatible_types(old_m->GetType(), new_m->GetType());

    const auto& old_args = old_m->GetArguments();
    const auto& new_args = new_m->GetArguments();
    // this is guaranteed because arguments are part of AidlMethod::Signature()
    AIDL_FATAL_IF(old_args.size() != new_args.size(), old_m);
    for (size_t i = 0; i < old_args.size(); i++) {
      const AidlArgument& old_a = *(old_args.at(i));
      const AidlArgument& new_a = *(new_args.at(i));
      compatible &= are_compatible_types(old_a.GetType(), new_a.GetType());

      if (old_a.GetDirection() != new_a.GetDirection()) {
        AIDL_ERROR(new_m) << "Direction changed: " << old_a.GetDirectionSpecifier() << " to "
                          << new_a.GetDirectionSpecifier() << ".";
        compatible = false;
      }
    }
  }

  compatible = are_compatible_constants(older, newer) && compatible;

  return compatible;
}

static bool HasZeroEnumerator(const AidlEnumDeclaration& enum_decl) {
  return std::any_of(enum_decl.GetEnumerators().begin(), enum_decl.GetEnumerators().end(),
                     [&](const unique_ptr<AidlEnumerator>& enumerator) {
                       return enumerator->GetValue()->Literal() == "0";
                     });
}

static bool EvaluatesToZero(const AidlEnumDeclaration& enum_decl, const std::string& value) {
  if (value == "") return true;
  // Because --check_api runs with "valid" AIDL definitions, we can safely assume that
  // the value is formatted as <scope>.<enumerator>.
  auto enumerator_name = value.substr(value.find_last_of('.') + 1);
  for (const auto& enumerator : enum_decl.GetEnumerators()) {
    if (enumerator->GetName() == enumerator_name) {
      return enumerator->GetValue()->Literal() == "0";
    }
  }
  AIDL_FATAL(enum_decl) << "Can't find " << enumerator_name << " in " << enum_decl.GetName();
}

static bool are_compatible_parcelables(const AidlDefinedType& older, const AidlTypenames&,
                                       const AidlDefinedType& newer,
                                       const AidlTypenames& new_types) {
  const auto& old_fields = older.GetFields();
  const auto& new_fields = newer.GetFields();
  if (old_fields.size() > new_fields.size()) {
    // you can add new fields only at the end
    AIDL_ERROR(newer) << "Number of fields in " << older.GetCanonicalName() << " is reduced from "
                      << old_fields.size() << " to " << new_fields.size() << ".";
    return false;
  }
  if (newer.IsFixedSize() && old_fields.size() != new_fields.size()) {
    AIDL_ERROR(newer) << "Number of fields in " << older.GetCanonicalName() << " is changed from "
                      << old_fields.size() << " to " << new_fields.size()
                      << ". This is an incompatible change for FixedSize types.";
    return false;
  }

  // android.net.UidRangeParcel should be frozen to prevent breakage in legacy (b/186720556)
  if (older.GetCanonicalName() == "android.net.UidRangeParcel" &&
      old_fields.size() != new_fields.size()) {
    AIDL_ERROR(newer) << "Number of fields in " << older.GetCanonicalName() << " is changed from "
                      << old_fields.size() << " to " << new_fields.size()
                      << ". But it is forbidden because of legacy support.";
    return false;
  }

  bool compatible = true;
  for (size_t i = 0; i < old_fields.size(); i++) {
    const auto& old_field = old_fields.at(i);
    const auto& new_field = new_fields.at(i);
    compatible &= are_compatible_types(old_field->GetType(), new_field->GetType());

    string old_value = old_field->GetDefaultValue() ? old_field->GetDefaultValue()->Literal() : "";
    string new_value = new_field->GetDefaultValue() ? new_field->GetDefaultValue()->Literal() : "";

    if (old_value == new_value) {
      continue;
    }
    // For enum type fields, we accept setting explicit default value which is "zero"
    auto enum_decl = new_types.GetEnumDeclaration(new_field->GetType());
    if (old_value == "" && enum_decl && EvaluatesToZero(*enum_decl, new_value)) {
      continue;
    }

    AIDL_ERROR(new_field) << "Changed default value: " << old_value << " to " << new_value << ".";
    compatible = false;
  }

  // Reordering of fields is an incompatible change.
  for (size_t i = 0; i < new_fields.size(); i++) {
    const auto& new_field = new_fields.at(i);
    auto found = std::find_if(old_fields.begin(), old_fields.end(), [&new_field](const auto& f) {
      return new_field->GetName() == f->GetName();
    });
    if (found != old_fields.end()) {
      size_t old_index = std::distance(old_fields.begin(), found);
      if (old_index != i) {
        AIDL_ERROR(new_field) << "Reordered " << new_field->GetName() << " from " << old_index
                              << " to " << i << ".";
        compatible = false;
      }
    }
  }

  for (size_t i = old_fields.size(); i < new_fields.size(); i++) {
    const auto& new_field = new_fields.at(i);
    if (new_field->HasUsefulDefaultValue()) {
      continue;
    }

    // enum can't be nullable, but it's okay if it has 0 as a valid enumerator.
    if (const auto& enum_decl = new_types.GetEnumDeclaration(new_field->GetType());
        enum_decl != nullptr) {
      if (HasZeroEnumerator(*enum_decl)) {
        continue;
      }

      // TODO(b/142893595): Rephrase the message: "provide a default value or make sure ..."
      AIDL_ERROR(new_field) << "Field '" << new_field->GetName() << "' of enum '"
                            << enum_decl->GetName()
                            << "' can't be initialized as '0'. Please make sure '"
                            << enum_decl->GetName() << "' has '0' as a valid value.";
      compatible = false;
      continue;
    }

    // Old API versions may suffer from the issue presented here. There is
    // only a finite number in Android, which we must allow indefinitely.
    struct HistoricalException {
      std::string canonical;
      std::string field;
    };
    static std::vector<HistoricalException> exceptions = {
        {"android.net.DhcpResultsParcelable", "serverHostName"},
        {"android.net.ResolverParamsParcel", "resolverOptions"},
    };
    bool excepted = false;
    for (const HistoricalException& exception : exceptions) {
      if (older.GetCanonicalName() == exception.canonical &&
          new_field->GetName() == exception.field) {
        excepted = true;
        break;
      }
    }
    if (excepted) continue;

    AIDL_ERROR(new_field)
        << "Field '" << new_field->GetName()
        << "' does not have a useful default in some backends. Please either provide a default "
           "value for this field or mark the field as @nullable. This value or a null value will "
           "be used automatically when an old version of this parcelable is sent to a process "
           "which understands a new version of this parcelable. In order to make sure your code "
           "continues to be backwards compatible, make sure the default or null value does not "
           "cause a semantic change to this parcelable.";
    compatible = false;
  }

  compatible = are_compatible_constants(older, newer) && compatible;

  return compatible;
}

static bool are_compatible_enums(const AidlEnumDeclaration& older,
                                 const AidlEnumDeclaration& newer) {
  if (!are_compatible_types(older.GetBackingType(), newer.GetBackingType())) {
    AIDL_ERROR(newer) << "Changed backing types.";
    return false;
  }

  std::map<std::string, const AidlConstantValue*> old_enum_map;
  for (const auto& enumerator : older.GetEnumerators()) {
    old_enum_map[enumerator->GetName()] = enumerator->GetValue();
  }
  std::map<std::string, const AidlConstantValue*> new_enum_map;
  for (const auto& enumerator : newer.GetEnumerators()) {
    new_enum_map[enumerator->GetName()] = enumerator->GetValue();
  }

  bool compatible = true;
  for (const auto& [name, value] : old_enum_map) {
    if (new_enum_map.find(name) == new_enum_map.end()) {
      AIDL_ERROR(newer) << "Removed enumerator from " << older.GetCanonicalName() << ": " << name;
      compatible = false;
      continue;
    }
    const string old_value = old_enum_map[name]->Literal();
    const string new_value = new_enum_map[name]->Literal();
    if (old_value != new_value) {
      AIDL_ERROR(newer) << "Changed enumerator value: " << older.GetCanonicalName() << "::" << name
                        << " from " << old_value << " to " << new_value << ".";
      compatible = false;
    }
  }
  return compatible;
}

static Result<AidlTypenames> load_from_dir(const Options& options, const IoDelegate& io_delegate,
                                           const std::string& dir) {
  Result<std::vector<std::string>> dir_files = io_delegate.ListFiles(dir);
  if (!dir_files.ok()) {
    AIDL_ERROR(dir) << dir_files.error();
    return Error();
  }

  AidlTypenames typenames;
  for (const auto& file : *dir_files) {
    if (!android::base::EndsWith(file, ".aidl")) continue;
    if (internals::load_and_validate_aidl(file, options, io_delegate, &typenames,
                                          nullptr /* imported_files */) != AidlError::OK) {
      AIDL_ERROR(file) << "Failed to read.";
      return Error();
    }
  }

  return typenames;
}

bool check_api(const Options& options, const IoDelegate& io_delegate) {
  AIDL_FATAL_IF(!options.IsStructured(), AIDL_LOCATION_HERE);
  AIDL_FATAL_IF(options.InputFiles().size() != 2, AIDL_LOCATION_HERE)
      << "--checkapi requires two inputs "
      << "but got " << options.InputFiles().size();
  auto old_tns = load_from_dir(options, io_delegate, options.InputFiles().at(0));
  if (!old_tns.ok()) {
    return false;
  }
  auto new_tns = load_from_dir(options, io_delegate, options.InputFiles().at(1));
  if (!new_tns.ok()) {
    return false;
  }

  const Options::CheckApiLevel level = options.GetCheckApiLevel();

  std::vector<AidlDefinedType*> old_types = old_tns->AllDefinedTypes();
  std::vector<AidlDefinedType*> new_types = new_tns->AllDefinedTypes();

  bool compatible = true;

  if (level == Options::CheckApiLevel::EQUAL) {
    std::set<string> old_type_names;
    for (const auto t : old_types) {
      old_type_names.insert(t->GetCanonicalName());
    }
    for (const auto new_type : new_types) {
      const auto found = old_type_names.find(new_type->GetCanonicalName());
      if (found == old_type_names.end()) {
        AIDL_ERROR(new_type) << "Added type: " << new_type->GetCanonicalName();
        compatible = false;
        continue;
      }
    }
  }

  map<string, AidlDefinedType*> new_map;
  for (const auto t : new_types) {
    new_map.emplace(t->GetCanonicalName(), t);
  }

  for (const auto old_type : old_types) {
    const auto found = new_map.find(old_type->GetCanonicalName());
    if (found == new_map.end()) {
      AIDL_ERROR(old_type) << "Removed type: " << old_type->GetCanonicalName();
      compatible = false;
      continue;
    }
    const auto new_type = found->second;

    if (level == Options::CheckApiLevel::EQUAL) {
      if (!CheckEquality(*old_type, *new_type)) {
        compatible = false;
      }
      continue;
    }

    if (!have_compatible_annotations(*old_type, *new_type)) {
      compatible = false;
    }
    if (old_type->AsInterface() != nullptr) {
      if (new_type->AsInterface() == nullptr) {
        AIDL_ERROR(new_type) << "Type mismatch: " << old_type->GetCanonicalName()
                             << " is changed from " << old_type->GetPreprocessDeclarationName()
                             << " to " << new_type->GetPreprocessDeclarationName();
        compatible = false;
        continue;
      }
      compatible &=
          are_compatible_interfaces(*(old_type->AsInterface()), *(new_type->AsInterface()));
    } else if (old_type->AsStructuredParcelable() != nullptr) {
      if (new_type->AsStructuredParcelable() == nullptr) {
        AIDL_ERROR(new_type) << "Parcelable" << new_type->GetCanonicalName()
                             << " is not structured. ";
        compatible = false;
        continue;
      }
      compatible &= are_compatible_parcelables(*(old_type->AsStructuredParcelable()), *old_tns,
                                               *(new_type->AsStructuredParcelable()), *new_tns);
    } else if (old_type->AsUnionDeclaration() != nullptr) {
      if (new_type->AsUnionDeclaration() == nullptr) {
        AIDL_ERROR(new_type) << "Type mismatch: " << old_type->GetCanonicalName()
                             << " is changed from " << old_type->GetPreprocessDeclarationName()
                             << " to " << new_type->GetPreprocessDeclarationName();
        compatible = false;
        continue;
      }
      compatible &= are_compatible_parcelables(*(old_type->AsUnionDeclaration()), *old_tns,
                                               *(new_type->AsUnionDeclaration()), *new_tns);
    } else if (old_type->AsEnumDeclaration() != nullptr) {
      if (new_type->AsEnumDeclaration() == nullptr) {
        AIDL_ERROR(new_type) << "Type mismatch: " << old_type->GetCanonicalName()
                             << " is changed from " << old_type->GetPreprocessDeclarationName()
                             << " to " << new_type->GetPreprocessDeclarationName();
        compatible = false;
        continue;
      }
      compatible &=
          are_compatible_enums(*(old_type->AsEnumDeclaration()), *(new_type->AsEnumDeclaration()));
    } else {
      AIDL_ERROR(old_type) << "Unsupported type " << old_type->GetPreprocessDeclarationName()
                           << " for " << old_type->GetCanonicalName();
      compatible = false;
    }
  }

  return compatible;
}

}  // namespace aidl
}  // namespace android
