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

#include "androidfw/Source.h"
#include "trace/TraceBuffer.h"
#include "util/Files.h"
#include "util/Util.h"
#include "utils/FileMap.h"
#include "ziparchive/zip_archive.h"

using ::android::StringPiece;

namespace aapt {
namespace io {

ZipFile::ZipFile(ZipArchiveHandle handle, const ZipEntry& entry, const android::Source& source)
    : zip_handle_(handle), zip_entry_(entry), source_(source) {
}

std::unique_ptr<IData> ZipFile::OpenAsData() {
  // The file will fail to be mmaped if it is empty
  if (zip_entry_.uncompressed_length == 0) {
    return util::make_unique<EmptyData>();
  }

  if (zip_entry_.method == kCompressStored) {
    int fd = GetFileDescriptor(zip_handle_);

    android::FileMap file_map;
    bool result = file_map.create(nullptr, fd, zip_entry_.offset,
                                  zip_entry_.uncompressed_length, true);
    if (!result) {
      return {};
    }
    return util::make_unique<MmappedData>(std::move(file_map));

  } else {
    std::unique_ptr<uint8_t[]> data =
        std::unique_ptr<uint8_t[]>(new uint8_t[zip_entry_.uncompressed_length]);
    int32_t result =
        ExtractToMemory(zip_handle_, &zip_entry_, data.get(),
                        static_cast<uint32_t>(zip_entry_.uncompressed_length));
    if (result != 0) {
      return {};
    }
    return util::make_unique<MallocData>(std::move(data),
                                         zip_entry_.uncompressed_length);
  }
}

std::unique_ptr<io::InputStream> ZipFile::OpenInputStream() {
  return OpenAsData();
}

const android::Source& ZipFile::GetSource() const {
  return source_;
}

bool ZipFile::WasCompressed() {
  return zip_entry_.method != kCompressStored;
}

ZipFileCollectionIterator::ZipFileCollectionIterator(
    ZipFileCollection* collection)
    : current_(collection->files_.begin()), end_(collection->files_.end()) {}

bool ZipFileCollectionIterator::HasNext() {
  return current_ != end_;
}

IFile* ZipFileCollectionIterator::Next() {
  IFile* result = current_->get();
  ++current_;
  return result;
}

ZipFileCollection::ZipFileCollection() : handle_(nullptr) {}

std::unique_ptr<ZipFileCollection> ZipFileCollection::Create(StringPiece path,
                                                             std::string* out_error) {
  TRACE_CALL();
  constexpr static const int32_t kEmptyArchive = -6;

  std::unique_ptr<ZipFileCollection> collection =
      std::unique_ptr<ZipFileCollection>(new ZipFileCollection());

  int32_t result = OpenArchive(path.data(), &collection->handle_);
  if (result != 0) {
    // If a zip is empty, result will be an error code. This is fine and we
    // should
    // return an empty ZipFileCollection.
    if (result == kEmptyArchive) {
      return collection;
    }

    if (out_error) *out_error = ErrorCodeString(result);
    return {};
  }

  void* cookie = nullptr;
  result = StartIteration(collection->handle_, &cookie);
  if (result != 0) {
    if (out_error) *out_error = ErrorCodeString(result);
    return {};
  }

  using IterationEnder = std::unique_ptr<void, decltype(EndIteration)*>;
  IterationEnder iteration_ender(cookie, EndIteration);

  std::string zip_entry_path;
  ZipEntry zip_data;
  while ((result = Next(cookie, &zip_data, &zip_entry_path)) == 0) {
    // Do not add folders to the file collection
    if (util::EndsWith(zip_entry_path, "/")) {
      continue;
    }

    std::unique_ptr<IFile> file = util::make_unique<ZipFile>(collection->handle_, zip_data,
                                                             android::Source(zip_entry_path, path));
    collection->files_by_name_[zip_entry_path] = file.get();
    collection->files_.push_back(std::move(file));
  }

  if (result != -1) {
    if (out_error) *out_error = ErrorCodeString(result);
    return {};
  }

  return collection;
}

IFile* ZipFileCollection::FindFile(StringPiece path) {
  auto iter = files_by_name_.find(path);
  if (iter != files_by_name_.end()) {
    return iter->second;
  }
  return nullptr;
}

std::unique_ptr<IFileCollectionIterator> ZipFileCollection::Iterator() {
  return util::make_unique<ZipFileCollectionIterator>(this);
}

char ZipFileCollection::GetDirSeparator() {
  // According to the zip file specification, section  4.4.17.1:
  // "All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' for compatibility
  // with Amiga and UNIX file systems etc."
  return '/';
}

ZipFileCollection::~ZipFileCollection() {
  if (handle_) {
    CloseArchive(handle_);
  }
}

}  // namespace io
}  // namespace aapt
