// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "libcef/browser/zip_reader_impl.h"
#include <time.h>
#include "base/logging.h"
#include "include/cef_stream.h"

// Static functions

// static
CefRefPtr<CefZipReader> CefZipReader::Create(
    CefRefPtr<CefStreamReader> stream) {
  CefRefPtr<CefZipReaderImpl> impl(new CefZipReaderImpl());
  if (!impl->Initialize(stream))
    return nullptr;
  return impl.get();
}

// CefZipReaderImpl

namespace {

voidpf ZCALLBACK zlib_open_callback OF((voidpf opaque,
                                        const void* filename,
                                        int mode)) {
  // The stream is already implicitly open so just return the pointer.
  return opaque;
}

uLong ZCALLBACK zlib_read_callback
OF((voidpf opaque, voidpf stream, void* buf, uLong size)) {
  CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
  return reader->Read(buf, 1, size);
}

ZPOS64_T ZCALLBACK zlib_tell_callback OF((voidpf opaque, voidpf stream)) {
  CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
  return reader->Tell();
}

long ZCALLBACK zlib_seek_callback
OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)) {
  CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
  int whence;
  switch (origin) {
    case ZLIB_FILEFUNC_SEEK_CUR:
      whence = SEEK_CUR;
      break;
    case ZLIB_FILEFUNC_SEEK_END:
      whence = SEEK_END;
      break;
    case ZLIB_FILEFUNC_SEEK_SET:
      whence = SEEK_SET;
      break;
    default:
      NOTREACHED();
      return -1;
  }
  return reader->Seek(offset, whence);
}

int ZCALLBACK zlib_close_callback OF((voidpf opaque, voidpf stream)) {
  CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(opaque));
  // Release the reference added by CefZipReaderImpl::Initialize().
  reader->Release();
  return 0;
}

int ZCALLBACK zlib_error_callback OF((voidpf opaque, voidpf stream)) {
  return 0;
}

}  // namespace

CefZipReaderImpl::CefZipReaderImpl()
    : supported_thread_id_(base::PlatformThread::CurrentId()),
      reader_(nullptr),
      has_fileopen_(false),
      has_fileinfo_(false),
      filesize_(0),
      filemodified_(0) {}

CefZipReaderImpl::~CefZipReaderImpl() {
  if (reader_ != nullptr) {
    if (!VerifyContext()) {
      // Close() is supposed to be called directly. We'll try to free the reader
      // now on the wrong thread but there's no guarantee this call won't crash.
      if (has_fileopen_)
        unzCloseCurrentFile(reader_);
      unzClose(reader_);
    } else {
      Close();
    }
  }
}

bool CefZipReaderImpl::Initialize(CefRefPtr<CefStreamReader> stream) {
  zlib_filefunc64_def filefunc_def;
  filefunc_def.zopen64_file = zlib_open_callback;
  filefunc_def.zread_file = zlib_read_callback;
  filefunc_def.zwrite_file = nullptr;
  filefunc_def.ztell64_file = zlib_tell_callback;
  filefunc_def.zseek64_file = zlib_seek_callback;
  filefunc_def.zclose_file = zlib_close_callback;
  filefunc_def.zerror_file = zlib_error_callback;
  filefunc_def.opaque = stream.get();

  // Add a reference that will be released by zlib_close_callback().
  stream->AddRef();

  reader_ = unzOpen2_64("", &filefunc_def);
  return (reader_ != nullptr);
}

bool CefZipReaderImpl::MoveToFirstFile() {
  if (!VerifyContext())
    return false;

  if (has_fileopen_)
    CloseFile();

  has_fileinfo_ = false;

  return (unzGoToFirstFile(reader_) == UNZ_OK);
}

bool CefZipReaderImpl::MoveToNextFile() {
  if (!VerifyContext())
    return false;

  if (has_fileopen_)
    CloseFile();

  has_fileinfo_ = false;

  return (unzGoToNextFile(reader_) == UNZ_OK);
}

bool CefZipReaderImpl::MoveToFile(const CefString& fileName,
                                  bool caseSensitive) {
  if (!VerifyContext())
    return false;

  if (has_fileopen_)
    CloseFile();

  has_fileinfo_ = false;

  std::string fileNameStr = fileName;
  return (unzLocateFile(reader_, fileNameStr.c_str(),
                        (caseSensitive ? 1 : 2)) == UNZ_OK);
}

bool CefZipReaderImpl::Close() {
  if (!VerifyContext())
    return false;

  if (has_fileopen_)
    CloseFile();

  int result = unzClose(reader_);
  reader_ = nullptr;
  return (result == UNZ_OK);
}

CefString CefZipReaderImpl::GetFileName() {
  if (!VerifyContext() || !GetFileInfo())
    return CefString();

  return filename_;
}

int64 CefZipReaderImpl::GetFileSize() {
  if (!VerifyContext() || !GetFileInfo())
    return -1;

  return filesize_;
}

CefTime CefZipReaderImpl::GetFileLastModified() {
  CefTime time;
  if (!VerifyContext() || !GetFileInfo())
    return time;

  cef_time_from_timet(filemodified_, &time);
  return time;
}

bool CefZipReaderImpl::OpenFile(const CefString& password) {
  if (!VerifyContext())
    return false;

  if (has_fileopen_)
    CloseFile();

  bool ret;

  if (password.empty()) {
    ret = (unzOpenCurrentFile(reader_) == UNZ_OK);
  } else {
    std::string passwordStr = password;
    ret = (unzOpenCurrentFilePassword(reader_, passwordStr.c_str()) == UNZ_OK);
  }

  if (ret)
    has_fileopen_ = true;
  return ret;
}

bool CefZipReaderImpl::CloseFile() {
  if (!VerifyContext() || !has_fileopen_)
    return false;

  has_fileopen_ = false;
  has_fileinfo_ = false;

  return (unzCloseCurrentFile(reader_) == UNZ_OK);
}

int CefZipReaderImpl::ReadFile(void* buffer, size_t bufferSize) {
  if (!VerifyContext() || !has_fileopen_)
    return -1;

  return unzReadCurrentFile(reader_, buffer, bufferSize);
}

int64 CefZipReaderImpl::Tell() {
  if (!VerifyContext() || !has_fileopen_)
    return -1;

  return unztell64(reader_);
}

bool CefZipReaderImpl::Eof() {
  if (!VerifyContext() || !has_fileopen_)
    return true;

  return (unzeof(reader_) == 1 ? true : false);
}

bool CefZipReaderImpl::GetFileInfo() {
  if (has_fileinfo_)
    return true;

  char file_name[512] = {0};
  unz_file_info file_info;
  memset(&file_info, 0, sizeof(file_info));

  if (unzGetCurrentFileInfo(reader_, &file_info, file_name, sizeof(file_name),
                            NULL, 0, NULL, 0) != UNZ_OK) {
    return false;
  }

  has_fileinfo_ = true;
  filename_ = std::string(file_name);
  filesize_ = file_info.uncompressed_size;

  struct tm time;
  memset(&time, 0, sizeof(time));
  time.tm_sec = file_info.tmu_date.tm_sec;
  time.tm_min = file_info.tmu_date.tm_min;
  time.tm_hour = file_info.tmu_date.tm_hour;
  time.tm_mday = file_info.tmu_date.tm_mday;
  time.tm_mon = file_info.tmu_date.tm_mon;
  time.tm_year = file_info.tmu_date.tm_year - 1900;  // Years since 1900.
  filemodified_ = mktime(&time);
  DCHECK_NE(filemodified_, (time_t)-1);

  return true;
}

bool CefZipReaderImpl::VerifyContext() {
  if (base::PlatformThread::CurrentId() != supported_thread_id_) {
    // This object should only be accessed from the thread that created it.
    NOTREACHED();
    return false;
  }

  return (reader_ != nullptr);
}
