/*
 * Copyright (C) 2017 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 "Convert.h"

#include <vector>

#include "android-base/macros.h"
#include "androidfw/StringPiece.h"

#include "LoadedApk.h"
#include "ValueVisitor.h"
#include "cmd/Util.h"
#include "format/binary/TableFlattener.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "format/proto/ProtoSerialize.h"
#include "io/BigBufferStream.h"
#include "io/Util.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
#include "util/Util.h"

using ::android::StringPiece;
using ::android::base::StringPrintf;
using ::std::unique_ptr;
using ::std::vector;

namespace aapt {

class IApkSerializer {
 public:
  IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {}

  virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
                            IArchiveWriter* writer) = 0;
  virtual bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) = 0;
  virtual bool SerializeFile(FileReference* file, IArchiveWriter* writer) = 0;

  virtual ~IApkSerializer() = default;

 protected:
  IAaptContext* context_;
  Source source_;
};

bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer* serializer,
                IArchiveWriter* writer) {
  if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer)) {
    context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                     << "failed to serialize AndroidManifest.xml");
    return false;
  }

  if (apk->GetResourceTable() != nullptr) {
    // The table might be modified by below code.
    auto converted_table = apk->GetResourceTable();

    // Resources
    for (const auto& package : converted_table->packages) {
      for (const auto& type : package->types) {
        for (const auto& entry : type->entries) {
          for (const auto& config_value : entry->values) {
            FileReference* file = ValueCast<FileReference>(config_value->value.get());
            if (file != nullptr) {
              if (file->file == nullptr) {
                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                                 << "no file associated with " << *file);
                return false;
              }

              if (!serializer->SerializeFile(file, writer)) {
                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                                 << "failed to serialize file " << *file->path);
                return false;
              }
            } // file
          } // config_value
        } // entry
      } // type
    } // package

    // Converted resource table
    if (!serializer->SerializeTable(converted_table, writer)) {
      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                       << "failed to serialize the resource table");
      return false;
    }
  }

  // Other files
  std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
  while (iterator->HasNext()) {
    io::IFile* file = iterator->Next();

    std::string path = file->GetSource().path;
    // The name of the path has the format "<zip-file-name>@<path-to-file>".
    path = path.substr(path.find('@') + 1);

    // Manifest, resource table and resources have already been taken care of.
    if (path == kAndroidManifestPath ||
        path == kApkResourceTablePath ||
        path == kProtoResourceTablePath ||
        path.find("res/") == 0) {
      continue;
    }

    if (!io::CopyFileToArchivePreserveCompression(context, file, path, writer)) {
      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                       << "failed to copy file " << path);
      return false;
    }
  }

  return true;
}


class BinaryApkSerializer : public IApkSerializer {
 public:
  BinaryApkSerializer(IAaptContext* context, const Source& source,
                   const TableFlattenerOptions& options)
      : IApkSerializer(context, source), tableFlattenerOptions_(options) {}

  bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
                    IArchiveWriter* writer) override {
    BigBuffer buffer(4096);
    XmlFlattenerOptions options = {};
    options.use_utf16 = utf16;
    options.keep_raw_values = true;
    XmlFlattener flattener(&buffer, options);
    if (!flattener.Consume(context_, xml)) {
      return false;
    }

    io::BigBufferInputStream input_stream(&buffer);
    return io::CopyInputStreamToArchive(context_, &input_stream, path, ArchiveEntry::kCompress,
                                        writer);
  }

  bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
    BigBuffer buffer(4096);
    TableFlattener table_flattener(tableFlattenerOptions_, &buffer);
    if (!table_flattener.Consume(context_, table)) {
      return false;
    }

    io::BigBufferInputStream input_stream(&buffer);
    return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath,
                                        ArchiveEntry::kAlign, writer);
  }

  bool SerializeFile(FileReference* file, IArchiveWriter* writer) override {
    if (file->type == ResourceFile::Type::kProtoXml) {
      unique_ptr<io::InputStream> in = file->file->OpenInputStream();
      if (in == nullptr) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to open file " << *file->path);
        return false;
      }

      pb::XmlNode pb_node;
      io::ZeroCopyInputAdaptor adaptor(in.get());
      if (!pb_node.ParseFromZeroCopyStream(&adaptor)) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to parse proto XML " << *file->path);
        return false;
      }

      std::string error;
      unique_ptr<xml::XmlResource> xml = DeserializeXmlResourceFromPb(pb_node, &error);
      if (xml == nullptr) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to deserialize proto XML "
                                          << *file->path << ": " << error);
        return false;
      }

      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to serialize to binary XML: " << *file->path);
        return false;
      }

      file->type = ResourceFile::Type::kBinaryXml;
    } else {
      if (!io::CopyFileToArchivePreserveCompression(context_, file->file, *file->path, writer)) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to copy file " << *file->path);
        return false;
      }
    }

    return true;
  }

 private:
  TableFlattenerOptions tableFlattenerOptions_;

  DISALLOW_COPY_AND_ASSIGN(BinaryApkSerializer);
};

class ProtoApkSerializer : public IApkSerializer {
 public:
  ProtoApkSerializer(IAaptContext* context, const Source& source)
      : IApkSerializer(context, source) {}

  bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
                    IArchiveWriter* writer) override {
    pb::XmlNode pb_node;
    SerializeXmlResourceToPb(*xml, &pb_node);
    return io::CopyProtoToArchive(context_, &pb_node, path, ArchiveEntry::kCompress, writer);
  }

  bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
    pb::ResourceTable pb_table;
    SerializeTableToPb(*table, &pb_table, context_->GetDiagnostics());
    return io::CopyProtoToArchive(context_, &pb_table, kProtoResourceTablePath,
                                  ArchiveEntry::kCompress, writer);
  }

  bool SerializeFile(FileReference* file, IArchiveWriter* writer) override {
    if (file->type == ResourceFile::Type::kBinaryXml) {
      std::unique_ptr<io::IData> data = file->file->OpenAsData();
      if (!data) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                         << "failed to open file " << *file->path);
        return false;
      }

      std::string error;
      std::unique_ptr<xml::XmlResource> xml = xml::Inflate(data->data(), data->size(), &error);
      if (xml == nullptr) {
        context_->GetDiagnostics()->Error(DiagMessage(source_) << "failed to parse binary XML: "
                                          << error);
        return false;
      }

      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to serialize to proto XML: " << *file->path);
        return false;
      }

      file->type = ResourceFile::Type::kProtoXml;
    } else {
      if (!io::CopyFileToArchivePreserveCompression(context_, file->file, *file->path, writer)) {
        context_->GetDiagnostics()->Error(DiagMessage(source_)
                                          << "failed to copy file " << *file->path);
        return false;
      }
    }

    return true;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ProtoApkSerializer);
};

class Context : public IAaptContext {
 public:
  Context() : mangler_({}), symbols_(&mangler_) {
  }

  PackageType GetPackageType() override {
    return PackageType::kApp;
  }

  SymbolTable* GetExternalSymbols() override {
    return &symbols_;
  }

  IDiagnostics* GetDiagnostics() override {
    return &diag_;
  }

  const std::string& GetCompilationPackage() override {
    return package_;
  }

  uint8_t GetPackageId() override {
    // Nothing should call this.
    UNIMPLEMENTED(FATAL) << "PackageID should not be necessary";
    return 0;
  }

  NameMangler* GetNameMangler() override {
    UNIMPLEMENTED(FATAL);
    return nullptr;
  }

  bool IsVerbose() override {
    return verbose_;
  }

  int GetMinSdkVersion() override {
    return 0u;
  }

  bool verbose_ = false;
  std::string package_;

 private:
  DISALLOW_COPY_AND_ASSIGN(Context);

  NameMangler mangler_;
  SymbolTable symbols_;
  StdErrDiagnostics diag_;
};

const char* ConvertCommand::kOutputFormatProto = "proto";
const char* ConvertCommand::kOutputFormatBinary = "binary";

int ConvertCommand::Action(const std::vector<std::string>& args) {
  if (args.size() != 1) {
    std::cerr << "must supply a single proto APK\n";
    Usage(&std::cerr);
    return 1;
  }

  Context context;
  const StringPiece& path = args[0];
  unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(path, context.GetDiagnostics());
  if (apk == nullptr) {
    context.GetDiagnostics()->Error(DiagMessage(path) << "failed to load APK");
    return 1;
  }

  Maybe<AppInfo> app_info =
      ExtractAppInfoFromBinaryManifest(*apk->GetManifest(), context.GetDiagnostics());
  if (!app_info) {
    return 1;
  }

  context.package_ = app_info.value().package;

  unique_ptr<IArchiveWriter> writer =
      CreateZipFileArchiveWriter(context.GetDiagnostics(), output_path_);
  if (writer == nullptr) {
    return 1;
  }

  unique_ptr<IApkSerializer> serializer;
  if (!output_format_ || output_format_.value() == ConvertCommand::kOutputFormatBinary) {

    serializer.reset(new BinaryApkSerializer(&context, apk->GetSource(), options_));
  } else if (output_format_.value() == ConvertCommand::kOutputFormatProto) {
    serializer.reset(new ProtoApkSerializer(&context, apk->GetSource()));
  } else {
    context.GetDiagnostics()->Error(DiagMessage(path)
        << "Invalid value for flag --output-format: "
        << output_format_.value());
    return 1;
  }

  return ConvertApk(&context, std::move(apk), serializer.get(), writer.get()) ? 0 : 1;
}

}  // namespace aapt
