// Copyright 2015 The Fuchsia 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 "src/lib/icu_data/cpp/icu_data.h"

#include <lib/syslog/cpp/macros.h>
#include <lib/zx/vmar.h>
#include <zircon/errors.h>

#include <fstream>
#include <optional>
#include <string>

#include <src/lib/files/directory.h>

#include "src/lib/fsl/vmo/file.h"
#include "src/lib/fsl/vmo/sized_vmo.h"
#include "third_party/icu/source/common/unicode/errorcode.h"
#include "third_party/icu/source/common/unicode/udata.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"

namespace icu_data {
namespace {

static constexpr char kIcuDataPath[] = "/pkg/data/icudtl.dat";

static uintptr_t g_icu_data_ptr = 0u;
static size_t g_icu_data_size = 0;

// Maximum number of bytes a revision ID length may be (e.g. "2019c").
static const size_t kRevisionIdLength = 5;

// Map the memory into the process and return a pointer to the memory.
// |size_out| is required and is set with the size of the mapped memory
// region.
uintptr_t GetData(const fsl::SizedVmo& icu_data, size_t* size_out) {
  if (!size_out)
    return 0u;
  uint64_t data_size = icu_data.size();
  if (data_size > std::numeric_limits<size_t>::max())
    return 0u;

  uintptr_t data = 0u;
  zx_status_t status = zx::vmar::root_self()->map(
      ZX_VM_PERM_READ, 0, icu_data.vmo(), 0, static_cast<size_t>(data_size), &data);
  if (status == ZX_OK) {
    *size_out = static_cast<size_t>(data_size);
    return data;
  }

  return 0u;
}

}  // namespace

zx_status_t Initialize() { return InitializeWithTzResourceDir(nullptr); }

zx_status_t InitializeWithTzResourceDir(const char tz_files_dir[]) {
  return InitializeWithTzResourceDirAndValidate(tz_files_dir, nullptr);
}

zx_status_t InitializeWithTzResourceDirAndValidate(const char tz_files_dir[],
                                                   const char tz_revision_file_path[]) {
  if (g_icu_data_ptr) {
    // Don't allow calling Initialize twice.
    return ZX_ERR_ALREADY_BOUND;
  }

  if (tz_files_dir && !files::IsDirectory(tz_files_dir)) {
    return ZX_ERR_NOT_DIR;
  }

  if (tz_files_dir) {
    // This is how we configure ICU to load time zone resource files from a
    // separate directory. See
    // http://userguide.icu-project.org/datetime/timezone#TOC-ICU4C-TZ-Update-with-Drop-in-.res-files-ICU-54-and-newer-
    setenv("ICU_TIMEZONE_FILES_DIR", tz_files_dir,
           /* overwrite existing env variable */ 1);
  }

  std::optional<std::string> expected_tz_revision_id;
  if (tz_revision_file_path) {
    std::ifstream in(tz_revision_file_path);
    if (in.fail()) {
      FX_LOGS(WARNING) << "could not read: " << tz_revision_file_path;
      return ZX_ERR_IO;
    }
    expected_tz_revision_id =
        std::string(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>());
    if (expected_tz_revision_id->length() != kRevisionIdLength) {
      FX_LOGS(WARNING) << "corrupted time zone revision ID: " << expected_tz_revision_id.value();
      return ZX_ERR_IO_DATA_INTEGRITY;
    }
  } else {
    expected_tz_revision_id = std::nullopt;
  }

  fsl::SizedVmo icu_data;
  if (!fsl::VmoFromFilename(kIcuDataPath, &icu_data)) {
    FX_LOGS(ERROR) << "could not create VMO from filename: " << kIcuDataPath;
    return ZX_ERR_IO;
  }

  size_t data_size = 0;
  uintptr_t data = GetData(icu_data, &data_size);

  // Pass the data to ICU.
  if (data) {
    UErrorCode err = U_ZERO_ERROR;
    udata_setCommonData(reinterpret_cast<const char*>(data), &err);
    g_icu_data_ptr = data;
    g_icu_data_size = data_size;
    if (err != U_ZERO_ERROR) {
      icu::ErrorCode ec;
      ec.set(err);
      FX_LOGS(WARNING) << "failed to set common data: " << ec.errorName();
      return ZX_ERR_INTERNAL;
    }

    // Validate tz revision ID if requested
    if (expected_tz_revision_id.has_value()) {
      const char* actual_tz_revision_id = icu::TimeZone::getTZDataVersion(err);
      if (err != U_ZERO_ERROR) {
        icu::ErrorCode ec;
        ec.set(err);
        FX_LOGS(WARNING) << "could not get tzdata version: " << ec.errorName();
        return ZX_ERR_INTERNAL;
      }
      if (expected_tz_revision_id != std::string(actual_tz_revision_id, kRevisionIdLength)) {
        FX_LOGS(WARNING) << "mismatched revision id: " << actual_tz_revision_id
                         << ", expected: " << expected_tz_revision_id.value();
        return ZX_ERR_IO_DATA_INTEGRITY;
      }
    }

    return ZX_OK;
  } else {
    Release();
    return ZX_ERR_INTERNAL;
  }
}

zx_status_t Release() {
  if (g_icu_data_ptr) {
    // Unmap the ICU data.
    zx_status_t status = zx::vmar::root_self()->unmap(g_icu_data_ptr, g_icu_data_size);
    g_icu_data_ptr = 0u;
    g_icu_data_size = 0;
    return status;
  } else {
    return ZX_ERR_BAD_STATE;
  }
}

}  // namespace icu_data
