// Copyright 2017 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 "garnet/bin/timezone/timezone.h"

#include <lib/fsl/vmo/file.h>
#include <lib/fsl/vmo/sized_vmo.h>
#include <lib/sys/cpp/component_context.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/strings/string_number_conversions.h>
#include <zircon/syscalls.h>

#include <fstream>

#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"

constexpr char kDefaultTimezone[] = "UTC";
constexpr int32_t kMillisecondsInMinute = 60000;

namespace time_zone {

TimezoneImpl::TimezoneImpl(std::unique_ptr<sys::ComponentContext> context,
                           const char icu_data_path[], const char tz_id_path[])
    : context_(std::move(context)),
      icu_data_path_(icu_data_path),
      tz_id_path_(tz_id_path),
      valid_(Init()) {
  context_->outgoing()->AddPublicService(bindings_.GetHandler(this));
  context_->outgoing()->AddPublicService(deprecated_bindings_.GetHandler(this));
}

TimezoneImpl::~TimezoneImpl() = default;

bool TimezoneImpl::Init() {
  fsl::SizedVmo icu_data;
  if (!fsl::VmoFromFilename(icu_data_path_, &icu_data)) {
    FXL_LOG(ERROR) << "Unable to load ICU data. Timezone data unavailable.";
    return false;
  }

  // Maps the ICU VMO into this process.
  uintptr_t icu_data_ptr = 0;
  if (zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ, 0, icu_data.vmo().get(),
                  0, icu_data.size(), &icu_data_ptr) != ZX_OK) {
    FXL_LOG(ERROR) << "Unable to map ICU data into process.";
    return false;
  }

  // ICU-related initialization.
  UErrorCode icu_set_data_status = U_ZERO_ERROR;
  udata_setCommonData(reinterpret_cast<void*>(icu_data_ptr),
                      &icu_set_data_status);
  if (icu_set_data_status != U_ZERO_ERROR) {
    FXL_LOG(ERROR) << "Unable to set common ICU data. "
                   << "Timezone data unavailable.";
    return false;
  }

  return true;
}

void TimezoneImpl::GetTimezoneOffsetMinutes(
    int64_t milliseconds_since_epoch,
    GetTimezoneOffsetMinutesCallback callback) {
  if (!valid_) {
    callback(0, 0);
    return;
  }
  fidl::StringPtr timezone_id = GetTimezoneIdImpl();
  std::unique_ptr<icu::TimeZone> timezone(
      icu::TimeZone::createTimeZone(timezone_id.get().c_str()));
  int32_t local_offset = 0, dst_offset = 0;
  UErrorCode error = U_ZERO_ERROR;
  // Local time is set to false, and local_offset/dst_offset/error are mutated
  // via non-const references.
  timezone->getOffset(static_cast<UDate>(milliseconds_since_epoch), false,
                      local_offset, dst_offset, error);
  if (error != U_ZERO_ERROR) {
    icu::ErrorCode icuError;
    icuError.set(error);
    FXL_LOG(ERROR) << "Unable to get correct offset: error code " << error
                   << " " << icuError.errorName();
    callback(0, 0);
    return;
  }
  local_offset /= kMillisecondsInMinute;
  dst_offset /= kMillisecondsInMinute;
  callback(local_offset, dst_offset);
}

void TimezoneImpl::NotifyWatchers(const fidl::StringPtr& new_timezone_id) {
  for (auto& watcher : watchers_) {
    watcher->OnTimezoneOffsetChange(new_timezone_id);
  }
  for (auto& watcher : deprecated_watchers_) {
    watcher->OnTimezoneOffsetChange(new_timezone_id);
  }
}

bool TimezoneImpl::IsValidTimezoneId(const fidl::StringPtr& timezone_id) {
  std::unique_ptr<icu::TimeZone> timezone(
      icu::TimeZone::createTimeZone(timezone_id.get().c_str()));
  if ((*timezone) == icu::TimeZone::getUnknown()) {
    return false;
  }
  return true;
}

void TimezoneImpl::SetTimezone(std::string timezone_id,
                               SetTimezoneCallback callback) {
  if (!valid_) {
    FXL_LOG(ERROR) << "Time service is not valid.";
    callback(false);
    return;
  }
  if (!IsValidTimezoneId(timezone_id)) {
    FXL_LOG(ERROR) << "Timezone '" << timezone_id << "' is not valid.";
    callback(false);
    return;
  }
  std::ofstream out_fstream(tz_id_path_, std::ofstream::trunc);
  if (!out_fstream.is_open()) {
    FXL_LOG(ERROR) << "Unable to open file for write '" << tz_id_path_ << "'";
    callback(false);
    return;
  }
  out_fstream << timezone_id;
  out_fstream.close();
  NotifyWatchers(timezone_id);
  callback(true);
}

void TimezoneImpl::GetTimezoneId(GetTimezoneIdCallback callback) {
  callback(GetTimezoneIdImpl());
}

fidl::StringPtr TimezoneImpl::GetTimezoneIdImpl() {
  if (!valid_) {
    return kDefaultTimezone;
  }
  std::ifstream in_fstream(tz_id_path_);
  if (!in_fstream.is_open()) {
    return kDefaultTimezone;
  }
  std::string id_str;
  in_fstream >> id_str;
  in_fstream.close();

  if (id_str.empty()) {
    FXL_LOG(ERROR) << "TZ file empty at '" << tz_id_path_ << "'";
    return kDefaultTimezone;
  }
  if (!IsValidTimezoneId(id_str)) {
    FXL_LOG(ERROR) << "Saved TZ ID invalid: '" << id_str << "'";
    return kDefaultTimezone;
  }
  return id_str;
}

void TimezoneImpl::ReleaseWatcher(fuchsia::timezone::TimezoneWatcher* watcher) {
  auto predicate = [watcher](const auto& target) {
    return target.get() == watcher;
  };
  watchers_.erase(
      std::remove_if(watchers_.begin(), watchers_.end(), predicate));
}

void TimezoneImpl::ReleaseWatcher(
    fuchsia::deprecatedtimezone::TimezoneWatcher* watcher) {
  auto predicate = [watcher](const auto& target) {
    return target.get() == watcher;
  };
  deprecated_watchers_.erase(std::remove_if(
      deprecated_watchers_.begin(), deprecated_watchers_.end(), predicate));
}

void TimezoneImpl::Watch(
    fidl::InterfaceHandle<fuchsia::timezone::TimezoneWatcher> watcher) {
  fuchsia::timezone::TimezoneWatcherPtr watcher_proxy = watcher.Bind();
  fuchsia::timezone::TimezoneWatcher* proxy_raw_ptr = watcher_proxy.get();
  watcher_proxy.set_error_handler([this, proxy_raw_ptr](zx_status_t status) {
    ReleaseWatcher(proxy_raw_ptr);
  });
  watchers_.push_back(std::move(watcher_proxy));
}

void TimezoneImpl::Watch(
    fidl::InterfaceHandle<fuchsia::deprecatedtimezone::TimezoneWatcher>
        watcher) {
  fuchsia::deprecatedtimezone::TimezoneWatcherPtr watcher_proxy =
      watcher.Bind();
  fuchsia::deprecatedtimezone::TimezoneWatcher* proxy_raw_ptr =
      watcher_proxy.get();
  watcher_proxy.set_error_handler([this, proxy_raw_ptr](zx_status_t status) {
    ReleaseWatcher(proxy_raw_ptr);
  });
  deprecated_watchers_.push_back(std::move(watcher_proxy));
}

}  // namespace time_zone
