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

#include "aidl.h"

#include <fcntl.h>
#include <iostream>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>

#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <sys/stat.h>
#endif

#include <android-base/strings.h>

#include "aidl_language.h"
#include "generate_cpp.h"
#include "generate_java.h"
#include "import_resolver.h"
#include "logging.h"
#include "options.h"
#include "os.h"
#include "type_cpp.h"
#include "type_java.h"
#include "type_namespace.h"

#ifndef O_BINARY
#  define O_BINARY  0
#endif

using android::base::Join;
using android::base::Split;
using std::cerr;
using std::endl;
using std::map;
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace android {
namespace aidl {
namespace {

// The following are gotten as the offset from the allowable id's between
// android.os.IBinder.FIRST_CALL_TRANSACTION=1 and
// android.os.IBinder.LAST_CALL_TRANSACTION=16777215
const int kMinUserSetMethodId = 0;
const int kMaxUserSetMethodId = 16777214;

bool check_filename(const std::string& filename,
                    const std::string& package,
                    const std::string& name,
                    unsigned line) {
    const char* p;
    string expected;
    string fn;
    size_t len;
    bool valid = false;

    if (!IoDelegate::GetAbsolutePath(filename, &fn)) {
      return false;
    }

    if (!package.empty()) {
        expected = package;
        expected += '.';
    }

    len = expected.length();
    for (size_t i=0; i<len; i++) {
        if (expected[i] == '.') {
            expected[i] = OS_PATH_SEPARATOR;
        }
    }

    expected.append(name, 0, name.find('.'));

    expected += ".aidl";

    len = fn.length();
    valid = (len >= expected.length());

    if (valid) {
        p = fn.c_str() + (len - expected.length());

#ifdef _WIN32
        if (OS_PATH_SEPARATOR != '/') {
            // Input filename under cygwin most likely has / separators
            // whereas the expected string uses \\ separators. Adjust
            // them accordingly.
          for (char *c = const_cast<char *>(p); *c; ++c) {
                if (*c == '/') *c = OS_PATH_SEPARATOR;
            }
        }
#endif

        // aidl assumes case-insensitivity on Mac Os and Windows.
#if defined(__linux__)
        valid = (expected == p);
#else
        valid = !strcasecmp(expected.c_str(), p);
#endif
    }

    if (!valid) {
        fprintf(stderr, "%s:%d interface %s should be declared in a file"
                " called %s.\n",
                filename.c_str(), line, name.c_str(), expected.c_str());
    }

    return valid;
}

bool check_filenames(const std::string& filename, const AidlDocument* doc) {
  if (!doc)
    return true;

  const AidlInterface* interface = doc->GetInterface();

  if (interface) {
    return check_filename(filename, interface->GetPackage(),
                          interface->GetName(), interface->GetLine());
  }

  bool success = true;

  for (const auto& item : doc->GetParcelables()) {
    success &= check_filename(filename, item->GetPackage(), item->GetName(),
                              item->GetLine());
  }

  return success;
}

bool gather_types(const std::string& filename,
                  const AidlDocument* doc,
                  TypeNamespace* types) {
  bool success = true;

  const AidlInterface* interface = doc->GetInterface();

  if (interface)
    return types->AddBinderType(*interface, filename);

  for (const auto& item : doc->GetParcelables()) {
    success &= types->AddParcelableType(*item, filename);
  }

  return success;
}

int check_types(const string& filename,
                const AidlInterface* c,
                TypeNamespace* types) {
  int err = 0;

  if (c->IsUtf8() && c->IsUtf8InCpp()) {
    cerr << filename << ":" << c->GetLine()
         << "Interface cannot be marked as both @utf8 and @utf8InCpp";
    err = 1;
  }

  // Has to be a pointer due to deleting copy constructor. No idea why.
  map<string, const AidlMethod*> method_names;
  for (const auto& m : c->GetMethods()) {
    bool oneway = m->IsOneway() || c->IsOneway();

    if (!types->MaybeAddContainerType(m->GetType())) {
      err = 1;  // return type is invalid
    }

    const ValidatableType* return_type =
        types->GetReturnType(m->GetType(), filename, *c);

    if (!return_type) {
      err = 1;
    }

    m->GetMutableType()->SetLanguageType(return_type);

    if (oneway && m->GetType().GetName() != "void") {
        cerr << filename << ":" << m->GetLine()
            << " oneway method '" << m->GetName() << "' cannot return a value"
            << endl;
        err = 1;
    }

    int index = 1;
    for (const auto& arg : m->GetArguments()) {
      if (!types->MaybeAddContainerType(arg->GetType())) {
        err = 1;
      }

      const ValidatableType* arg_type =
          types->GetArgType(*arg, index, filename, *c);

      if (!arg_type) {
        err = 1;
      }

      arg->GetMutableType()->SetLanguageType(arg_type);

      if (oneway && arg->IsOut()) {
        cerr << filename << ":" << m->GetLine()
            << " oneway method '" << m->GetName()
            << "' cannot have out parameters" << endl;
        err = 1;
      }
    }

    auto it = method_names.find(m->GetName());
    // prevent duplicate methods
    if (it == method_names.end()) {
      method_names[m->GetName()] = m.get();
    } else {
      cerr << filename << ":" << m->GetLine()
           << " attempt to redefine method " << m->GetName() << "," << endl
           << filename << ":" << it->second->GetLine()
           << "    previously defined here." << endl;
      err = 1;
    }
  }
  return err;
}

void write_common_dep_file(const string& output_file,
                           const vector<string>& aidl_sources,
                           CodeWriter* writer,
                           const bool ninja) {
  // Encode that the output file depends on aidl input files.
  writer->Write("%s : \\\n", output_file.c_str());
  writer->Write("  %s", Join(aidl_sources, " \\\n  ").c_str());
  writer->Write("\n");

  if (!ninja) {
    writer->Write("\n");
    // Output "<input_aidl_file>: " so make won't fail if the input .aidl file
    // has been deleted, moved or renamed in incremental build.
    for (const auto& src : aidl_sources) {
      writer->Write("%s :\n", src.c_str());
    }
  }
}

bool write_java_dep_file(const JavaOptions& options,
                         const vector<unique_ptr<AidlImport>>& imports,
                         const IoDelegate& io_delegate,
                         const string& output_file_name) {
  string dep_file_name = options.DependencyFilePath();
  if (dep_file_name.empty()) {
    return true;  // nothing to do
  }
  CodeWriterPtr writer = io_delegate.GetCodeWriter(dep_file_name);
  if (!writer) {
    LOG(ERROR) << "Could not open dependency file: " << dep_file_name;
    return false;
  }

  vector<string> source_aidl = {options.input_file_name_};
  for (const auto& import : imports) {
    if (!import->GetFilename().empty()) {
      source_aidl.push_back(import->GetFilename());
    }
  }

  write_common_dep_file(output_file_name, source_aidl, writer.get(),
                        options.DependencyFileNinja());

  return true;
}

bool write_cpp_dep_file(const CppOptions& options,
                        const AidlInterface& interface,
                        const vector<unique_ptr<AidlImport>>& imports,
                        const IoDelegate& io_delegate) {
  using ::android::aidl::cpp::HeaderFile;
  using ::android::aidl::cpp::ClassNames;

  string dep_file_name = options.DependencyFilePath();
  if (dep_file_name.empty()) {
    return true;  // nothing to do
  }
  CodeWriterPtr writer = io_delegate.GetCodeWriter(dep_file_name);
  if (!writer) {
    LOG(ERROR) << "Could not open dependency file: " << dep_file_name;
    return false;
  }

  vector<string> source_aidl = {options.InputFileName()};
  for (const auto& import : imports) {
    if (!import->GetFilename().empty()) {
      source_aidl.push_back(import->GetFilename());
    }
  }

  write_common_dep_file(options.OutputCppFilePath(), source_aidl, writer.get(),
                        options.DependencyFileNinja());

  if (!options.DependencyFileNinja()) {
    vector<string> headers;
    for (ClassNames c : {ClassNames::CLIENT,
                         ClassNames::SERVER,
                         ClassNames::INTERFACE}) {
      headers.push_back(options.OutputHeaderDir() + '/' +
                        HeaderFile(interface, c, false /* use_os_sep */));
    }

    writer->Write("\n");

    // Generated headers also depend on the source aidl files.
    writer->Write("%s : \\\n    %s\n", Join(headers, " \\\n    ").c_str(),
                  Join(source_aidl, " \\\n    ").c_str());
  }

  return true;
}

string generate_outputFileName(const JavaOptions& options,
                               const AidlInterface& interface) {
    const string& name = interface.GetName();
    string package = interface.GetPackage();
    string result;

    // create the path to the destination folder based on the
    // interface package name
    result = options.output_base_folder_;
    result += OS_PATH_SEPARATOR;

    string packageStr = package;
    size_t len = packageStr.length();
    for (size_t i=0; i<len; i++) {
        if (packageStr[i] == '.') {
            packageStr[i] = OS_PATH_SEPARATOR;
        }
    }

    result += packageStr;

    // add the filename by replacing the .aidl extension to .java
    result += OS_PATH_SEPARATOR;
    result.append(name, 0, name.find('.'));
    result += ".java";

    return result;
}

int check_and_assign_method_ids(const char * filename,
                                const std::vector<std::unique_ptr<AidlMethod>>& items) {
    // Check whether there are any methods with manually assigned id's and any that are not.
    // Either all method id's must be manually assigned or all of them must not.
    // Also, check for duplicates of user set id's and that the id's are within the proper bounds.
    set<int> usedIds;
    bool hasUnassignedIds = false;
    bool hasAssignedIds = false;
    for (const auto& item : items) {
        if (item->HasId()) {
            hasAssignedIds = true;
            // Ensure that the user set id is not duplicated.
            if (usedIds.find(item->GetId()) != usedIds.end()) {
                // We found a duplicate id, so throw an error.
                fprintf(stderr,
                        "%s:%d Found duplicate method id (%d) for method: %s\n",
                        filename, item->GetLine(),
                        item->GetId(), item->GetName().c_str());
                return 1;
            }
            // Ensure that the user set id is within the appropriate limits
            if (item->GetId() < kMinUserSetMethodId ||
                    item->GetId() > kMaxUserSetMethodId) {
                fprintf(stderr, "%s:%d Found out of bounds id (%d) for method: %s\n",
                        filename, item->GetLine(),
                        item->GetId(), item->GetName().c_str());
                fprintf(stderr, "    Value for id must be between %d and %d inclusive.\n",
                        kMinUserSetMethodId, kMaxUserSetMethodId);
                return 1;
            }
            usedIds.insert(item->GetId());
        } else {
            hasUnassignedIds = true;
        }
        if (hasAssignedIds && hasUnassignedIds) {
            fprintf(stderr,
                    "%s: You must either assign id's to all methods or to none of them.\n",
                    filename);
            return 1;
        }
    }

    // In the case that all methods have unassigned id's, set a unique id for them.
    if (hasUnassignedIds) {
        int newId = 0;
        for (const auto& item : items) {
            item->SetId(newId++);
        }
    }

    // success
    return 0;
}

bool validate_constants(const AidlInterface& interface) {
  bool success = true;
  set<string> names;
  for (const std::unique_ptr<AidlIntConstant>& int_constant :
       interface.GetIntConstants()) {
    if (names.count(int_constant->GetName()) > 0) {
      LOG(ERROR) << "Found duplicate constant name '" << int_constant->GetName()
                 << "'";
      success = false;
    }
    names.insert(int_constant->GetName());
    // We've logged an error message for this on object construction.
    success = success && int_constant->IsValid();
  }
  for (const std::unique_ptr<AidlStringConstant>& string_constant :
       interface.GetStringConstants()) {
    if (names.count(string_constant->GetName()) > 0) {
      LOG(ERROR) << "Found duplicate constant name '" << string_constant->GetName()
                 << "'";
      success = false;
    }
    names.insert(string_constant->GetName());
    // We've logged an error message for this on object construction.
    success = success && string_constant->IsValid();
  }
  return success;
}

// TODO: Remove this in favor of using the YACC parser b/25479378
bool ParsePreprocessedLine(const string& line, string* decl,
                           vector<string>* package, string* class_name) {
  // erase all trailing whitespace and semicolons
  const size_t end = line.find_last_not_of(" ;\t");
  if (end == string::npos) {
    return false;
  }
  if (line.rfind(';', end) != string::npos) {
    return false;
  }

  decl->clear();
  string type;
  vector<string> pieces = Split(line.substr(0, end + 1), " \t");
  for (const string& piece : pieces) {
    if (piece.empty()) {
      continue;
    }
    if (decl->empty()) {
      *decl = std::move(piece);
    } else if (type.empty()) {
      type = std::move(piece);
    } else {
      return false;
    }
  }

  // Note that this logic is absolutely wrong.  Given a parcelable
  // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
  // the class is just Bar.  However, this was the way it was done in the past.
  //
  // See b/17415692
  size_t dot_pos = type.rfind('.');
  if (dot_pos != string::npos) {
    *class_name = type.substr(dot_pos + 1);
    *package = Split(type.substr(0, dot_pos), ".");
  } else {
    *class_name = type;
    package->clear();
  }

  return true;
}

}  // namespace

namespace internals {

bool parse_preprocessed_file(const IoDelegate& io_delegate,
                             const string& filename, TypeNamespace* types) {
  bool success = true;
  unique_ptr<LineReader> line_reader = io_delegate.GetLineReader(filename);
  if (!line_reader) {
    LOG(ERROR) << "cannot open preprocessed file: " << filename;
    success = false;
    return success;
  }

  string line;
  unsigned lineno = 1;
  for ( ; line_reader->ReadLine(&line); ++lineno) {
    if (line.empty() || line.compare(0, 2, "//") == 0) {
      // skip comments and empty lines
      continue;
    }

    string decl;
    vector<string> package;
    string class_name;
    if (!ParsePreprocessedLine(line, &decl, &package, &class_name)) {
      success = false;
      break;
    }

    if (decl == "parcelable") {
      AidlParcelable doc(new AidlQualifiedName(class_name, ""),
                         lineno, package);
      types->AddParcelableType(doc, filename);
    } else if (decl == "interface") {
      auto temp = new std::vector<std::unique_ptr<AidlMember>>();
      AidlInterface doc(class_name, lineno, "", false, temp, package);
      types->AddBinderType(doc, filename);
    } else {
      success = false;
      break;
    }
  }
  if (!success) {
    LOG(ERROR) << filename << ':' << lineno
               << " malformed preprocessed file line: '" << line << "'";
  }

  return success;
}

AidlError load_and_validate_aidl(
    const std::vector<std::string>& preprocessed_files,
    const std::vector<std::string>& import_paths,
    const std::string& input_file_name,
    const IoDelegate& io_delegate,
    TypeNamespace* types,
    std::unique_ptr<AidlInterface>* returned_interface,
    std::vector<std::unique_ptr<AidlImport>>* returned_imports) {
  AidlError err = AidlError::OK;

  std::map<AidlImport*,std::unique_ptr<AidlDocument>> docs;

  // import the preprocessed file
  for (const string& s : preprocessed_files) {
    if (!parse_preprocessed_file(io_delegate, s, types)) {
      err = AidlError::BAD_PRE_PROCESSED_FILE;
    }
  }
  if (err != AidlError::OK) {
    return err;
  }

  // parse the input file
  Parser p{io_delegate};
  if (!p.ParseFile(input_file_name)) {
    return AidlError::PARSE_ERROR;
  }

  AidlDocument* parsed_doc = p.GetDocument();

  unique_ptr<AidlInterface> interface(parsed_doc->ReleaseInterface());

  if (!interface) {
    LOG(ERROR) << "refusing to generate code from aidl file defining "
                  "parcelable";
    return AidlError::FOUND_PARCELABLE;
  }

  if (!check_filename(input_file_name.c_str(), interface->GetPackage(),
                      interface->GetName(), interface->GetLine()) ||
      !types->IsValidPackage(interface->GetPackage())) {
    LOG(ERROR) << "Invalid package declaration '" << interface->GetPackage()
               << "'";
    return AidlError::BAD_PACKAGE;
  }

  // parse the imports of the input file
  ImportResolver import_resolver{io_delegate, import_paths};
  for (auto& import : p.GetImports()) {
    if (types->HasImportType(*import)) {
      // There are places in the Android tree where an import doesn't resolve,
      // but we'll pick the type up through the preprocessed types.
      // This seems like an error, but legacy support demands we support it...
      continue;
    }
    string import_path = import_resolver.FindImportFile(import->GetNeededClass());
    if (import_path.empty()) {
      cerr << import->GetFileFrom() << ":" << import->GetLine()
           << ": couldn't find import for class "
           << import->GetNeededClass() << endl;
      err = AidlError::BAD_IMPORT;
      continue;
    }
    import->SetFilename(import_path);

    Parser p{io_delegate};
    if (!p.ParseFile(import->GetFilename())) {
      cerr << "error while parsing import for class "
           << import->GetNeededClass() << endl;
      err = AidlError::BAD_IMPORT;
      continue;
    }

    std::unique_ptr<AidlDocument> document(p.ReleaseDocument());
    if (!check_filenames(import->GetFilename(), document.get()))
      err = AidlError::BAD_IMPORT;
    docs[import.get()] = std::move(document);
  }
  if (err != AidlError::OK) {
    return err;
  }

  // gather the types that have been declared
  if (!types->AddBinderType(*interface.get(), input_file_name)) {
    err = AidlError::BAD_TYPE;
  }

  interface->SetLanguageType(types->GetInterfaceType(*interface));

  for (const auto& import : p.GetImports()) {
    // If we skipped an unresolved import above (see comment there) we'll have
    // an empty bucket here.
    const auto import_itr = docs.find(import.get());
    if (import_itr == docs.cend()) {
      continue;
    }

    if (!gather_types(import->GetFilename(), import_itr->second.get(), types)) {
      err = AidlError::BAD_TYPE;
    }
  }

  // check the referenced types in parsed_doc to make sure we've imported them
  if (check_types(input_file_name, interface.get(), types) != 0) {
    err = AidlError::BAD_TYPE;
  }
  if (err != AidlError::OK) {
    return err;
  }


  // assign method ids and validate.
  if (check_and_assign_method_ids(input_file_name.c_str(),
                                  interface->GetMethods()) != 0) {
    return AidlError::BAD_METHOD_ID;
  }
  if (!validate_constants(*interface)) {
    return AidlError::BAD_CONSTANTS;
  }

  if (returned_interface)
    *returned_interface = std::move(interface);

  if (returned_imports)
    p.ReleaseImports(returned_imports);

  return AidlError::OK;
}

} // namespace internals

int compile_aidl_to_cpp(const CppOptions& options,
                        const IoDelegate& io_delegate) {
  unique_ptr<AidlInterface> interface;
  std::vector<std::unique_ptr<AidlImport>> imports;
  unique_ptr<cpp::TypeNamespace> types(new cpp::TypeNamespace());
  types->Init();
  AidlError err = internals::load_and_validate_aidl(
      std::vector<std::string>{},  // no preprocessed files
      options.ImportPaths(),
      options.InputFileName(),
      io_delegate,
      types.get(),
      &interface,
      &imports);
  if (err != AidlError::OK) {
    return 1;
  }

  if (!write_cpp_dep_file(options, *interface, imports, io_delegate)) {
    return 1;
  }

  return (cpp::GenerateCpp(options, *types, *interface, io_delegate)) ? 0 : 1;
}

int compile_aidl_to_java(const JavaOptions& options,
                         const IoDelegate& io_delegate) {
  unique_ptr<AidlInterface> interface;
  std::vector<std::unique_ptr<AidlImport>> imports;
  unique_ptr<java::JavaTypeNamespace> types(new java::JavaTypeNamespace());
  types->Init();
  AidlError aidl_err = internals::load_and_validate_aidl(
      options.preprocessed_files_,
      options.import_paths_,
      options.input_file_name_,
      io_delegate,
      types.get(),
      &interface,
      &imports);
  if (aidl_err == AidlError::FOUND_PARCELABLE && !options.fail_on_parcelable_) {
    // We aborted code generation because this file contains parcelables.
    // However, we were not told to complain if we find parcelables.
    // Just generate a dep file and exit quietly.  The dep file is for a legacy
    // use case by the SDK.
    write_java_dep_file(options, imports, io_delegate, "");
    return 0;
  }
  if (aidl_err != AidlError::OK) {
    return 1;
  }

  string output_file_name = options.output_file_name_;
  // if needed, generate the output file name from the base folder
  if (output_file_name.empty() && !options.output_base_folder_.empty()) {
    output_file_name = generate_outputFileName(options, *interface);
  }

  // make sure the folders of the output file all exists
  if (!io_delegate.CreatePathForFile(output_file_name)) {
    return 1;
  }

  if (!write_java_dep_file(options, imports, io_delegate, output_file_name)) {
    return 1;
  }

  return generate_java(output_file_name, options.input_file_name_.c_str(),
                       interface.get(), types.get(), io_delegate);
}

bool preprocess_aidl(const JavaOptions& options,
                     const IoDelegate& io_delegate) {
  unique_ptr<CodeWriter> writer =
      io_delegate.GetCodeWriter(options.output_file_name_);

  for (const auto& file : options.files_to_preprocess_) {
    Parser p{io_delegate};
    if (!p.ParseFile(file))
      return false;
    AidlDocument* doc = p.GetDocument();
    string line;

    const AidlInterface* interface = doc->GetInterface();

    if (interface != nullptr &&
        !writer->Write("interface %s;\n",
                       interface->GetCanonicalName().c_str())) {
      return false;
    }

    for (const auto& parcelable : doc->GetParcelables()) {
      if (!writer->Write("parcelable %s;\n",
                         parcelable->GetCanonicalName().c_str())) {
        return false;
      }
    }
  }

  return writer->Close();
}

}  // namespace android
}  // namespace aidl
