// Copyright (c) 2012 The Chromium 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 "chrome/browser/chromeos/mobile_config.h"

#include <algorithm>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace {

// Config attributes names.
const char kAcceptedConfigVersion[] = "1.0";
const char kDefaultAttr[] = "default";

// Carrier config attributes.
const char kCarriersAttr[] = "carriers";
const char kCarrierIdsAttr[] = "ids";
const char kCarrierIdAttr[] = "id";
const char kTopUpURLAttr[] = "top_up_url";
const char kShowPortalButtonAttr[] = "show_portal_button";
const char kDealsAttr[] = "deals";

// Carrier deal attributes.
const char kDealIdAttr[] = "deal_id";
const char kDealLocalesAttr[] = "locales";

const char kInfoURLAttr[] = "info_url";
const char kNotificationCountAttr[] = "notification_count";
const char kDealExpireDateAttr[] = "expire_date";
const char kLocalizedContentAttr[] = "localized_content";

// Initial locale carrier config attributes.
const char kInitialLocalesAttr[] = "initial_locales";
const char kSetupURLAttr[] = "setup_url";

// Local config properties.
const char kExcludeDealsAttr[] = "exclude_deals";

// Location of the global carrier config.
const char kGlobalCarrierConfigPath[] =
    "/usr/share/chromeos-assets/mobile/carrier_config.json";

// Location of the local carrier config.
const char kLocalCarrierConfigPath[] =
    "/opt/oem/etc/carrier_config.json";

}  // anonymous namespace

namespace chromeos {

// MobileConfig::CarrierDeal implementation. -----------------------------------

MobileConfig::CarrierDeal::CarrierDeal(const DictionaryValue* deal_dict)
    : notification_count_(0),
      localized_strings_(NULL) {
  deal_dict->GetString(kDealIdAttr, &deal_id_);

  // Extract list of deal locales.
  const ListValue* locale_list = NULL;
  if (deal_dict->GetList(kDealLocalesAttr, &locale_list)) {
    for (size_t i = 0; i < locale_list->GetSize(); ++i) {
      std::string locale;
      if (locale_list->GetString(i, &locale))
        locales_.push_back(locale);
    }
  }

  deal_dict->GetString(kInfoURLAttr, &info_url_);
  deal_dict->GetInteger(kNotificationCountAttr, &notification_count_);
  std::string date_string;
  if (deal_dict->GetString(kDealExpireDateAttr, &date_string)) {
    if (!base::Time::FromString(date_string.c_str(), &expire_date_))
      LOG(ERROR) << "Error parsing deal_expire_date: " << date_string;
  }
  deal_dict->GetDictionary(kLocalizedContentAttr, &localized_strings_);
}

MobileConfig::CarrierDeal::~CarrierDeal() {
}

std::string MobileConfig::CarrierDeal::GetLocalizedString(
    const std::string& locale, const std::string& id) const {
  std::string result;
  if (localized_strings_) {
    const DictionaryValue* locale_dict = NULL;
    if (localized_strings_->GetDictionary(locale, &locale_dict) &&
        locale_dict->GetString(id, &result)) {
      return result;
    } else if (localized_strings_->GetDictionary(kDefaultAttr, &locale_dict) &&
               locale_dict->GetString(id, &result)) {
      return result;
    }
  }
  return result;
}

// MobileConfig::Carrier implementation. ---------------------------------------

MobileConfig::Carrier::Carrier(const DictionaryValue* carrier_dict,
                               const std::string& initial_locale)
    : show_portal_button_(false) {
  InitFromDictionary(carrier_dict, initial_locale);
}

MobileConfig::Carrier::~Carrier() {
  RemoveDeals();
}

const MobileConfig::CarrierDeal* MobileConfig::Carrier::GetDefaultDeal() const {
  // TODO(nkostylev): Use carrier "default_deal_id" attribute.
  CarrierDeals::const_iterator iter = deals_.begin();
  if (iter != deals_.end())
    return GetDeal((*iter).first);
  else
    return NULL;
}

const MobileConfig::CarrierDeal* MobileConfig::Carrier::GetDeal(
    const std::string& deal_id) const {
  CarrierDeals::const_iterator iter = deals_.find(deal_id);
  if (iter != deals_.end()) {
    CarrierDeal* deal = iter->second;
    // Make sure that deal is still active,
    // i.e. if deal expire date is defined, check it.
    if (!deal->expire_date().is_null() &&
        deal->expire_date() <= base::Time::Now()) {
      return NULL;
    }
    return deal;
  } else {
    return NULL;
  }
}

void MobileConfig::Carrier::InitFromDictionary(
    const base::DictionaryValue* carrier_dict,
    const std::string& initial_locale) {
  carrier_dict->GetString(kTopUpURLAttr, &top_up_url_);
  carrier_dict->GetBoolean(kShowPortalButtonAttr, &show_portal_button_);

  bool exclude_deals = false;
  if (carrier_dict->GetBoolean(kExcludeDealsAttr, &exclude_deals) &&
      exclude_deals) {
    RemoveDeals();
  }

  // Extract list of external IDs for this carrier.
  const ListValue* id_list = NULL;
  if (carrier_dict->GetList(kCarrierIdsAttr, &id_list)) {
    for (size_t i = 0; i < id_list->GetSize(); ++i) {
      const DictionaryValue* id_dict = NULL;
      std::string external_id;
      if (id_list->GetDictionary(i, &id_dict) &&
          id_dict->GetString(kCarrierIdAttr, &external_id)) {
        external_ids_.push_back(external_id);
      }
    }
  }

  // Extract list of deals for this carrier.
  const ListValue* deals_list = NULL;
  if (carrier_dict->GetList(kDealsAttr, &deals_list)) {
    for (size_t i = 0; i < deals_list->GetSize(); ++i) {
      const DictionaryValue* deal_dict = NULL;
      if (deals_list->GetDictionary(i, &deal_dict)) {
        scoped_ptr<CarrierDeal> deal(new CarrierDeal(deal_dict));
        // Filter out deals by initial_locale right away.
        std::vector<std::string>::const_iterator iter =
            std::find(deal->locales().begin(),
                      deal->locales().end(),
                      initial_locale);
        if (iter != deal->locales().end()) {
          const std::string& deal_id = deal->deal_id();
          deals_[deal_id] = deal.release();
        }
      }
    }
  }
}

void MobileConfig::Carrier::RemoveDeals() {
  STLDeleteValues(&deals_);
}

// MobileConfig::LocaleConfig implementation. ----------------------------------

MobileConfig::LocaleConfig::LocaleConfig(DictionaryValue* locale_dict) {
  InitFromDictionary(locale_dict);
}

MobileConfig::LocaleConfig::~LocaleConfig() {
}

void MobileConfig::LocaleConfig::InitFromDictionary(
    base::DictionaryValue* locale_dict) {
  locale_dict->GetString(kSetupURLAttr, &setup_url_);
}

// MobileConfig implementation, public -----------------------------------------

// static
MobileConfig* MobileConfig::GetInstance() {
  return Singleton<MobileConfig,
      DefaultSingletonTraits<MobileConfig> >::get();
}

const MobileConfig::Carrier* MobileConfig::GetCarrier(
    const std::string& carrier_id) const {
  CarrierIdMap::const_iterator id_iter = carrier_id_map_.find(carrier_id);
  std::string internal_id;
  if (id_iter != carrier_id_map_.end())
    internal_id = id_iter->second;
  else
    return NULL;
  Carriers::const_iterator iter = carriers_.find(internal_id);
  if (iter != carriers_.end())
    return iter->second;
  else
    return NULL;
}

const MobileConfig::LocaleConfig* MobileConfig::GetLocaleConfig() const {
  return locale_config_.get();
}

// MobileConfig implementation, protected --------------------------------------

bool MobileConfig::LoadManifestFromString(const std::string& manifest) {
  if (!CustomizationDocument::LoadManifestFromString(manifest))
    return false;

  // Local config specific attribute.
  bool exclude_deals = false;
  if (root_.get() &&
      root_->GetBoolean(kExcludeDealsAttr, &exclude_deals) &&
      exclude_deals) {
    for (Carriers::iterator iter = carriers_.begin();
         iter != carriers_.end(); ++iter) {
      iter->second->RemoveDeals();
    }
  }

  // Other parts are optional and are the same among global/local config.
  DictionaryValue* carriers = NULL;
  if (root_.get() && root_->GetDictionary(kCarriersAttr, &carriers)) {
    for (DictionaryValue::Iterator iter(*carriers); !iter.IsAtEnd();
         iter.Advance()) {
      const DictionaryValue* carrier_dict = NULL;
      if (iter.value().GetAsDictionary(&carrier_dict)) {
        const std::string& internal_id = iter.key();
        Carriers::iterator inner_iter = carriers_.find(internal_id);
        if (inner_iter != carriers_.end()) {
          // Carrier already defined i.e. loading from the local config.
          // New ID mappings in local config is not supported.
          inner_iter->second->InitFromDictionary(carrier_dict, initial_locale_);
        } else {
          Carrier* carrier = new Carrier(carrier_dict, initial_locale_);
          if (!carrier->external_ids().empty()) {
            // Map all external IDs to a single internal one.
            for (std::vector<std::string>::const_iterator
                 i = carrier->external_ids().begin();
                 i != carrier->external_ids().end(); ++i) {
              carrier_id_map_[*i] = internal_id;
            }
          } else {
            // Trivial case - using same ID for external/internal one.
            carrier_id_map_[internal_id] = internal_id;
          }
          carriers_[internal_id] = carrier;
        }
      }
    }
  }

  DictionaryValue* initial_locales = NULL;
  if (root_.get() && root_->GetDictionary(kInitialLocalesAttr,
                                          &initial_locales)) {
    DictionaryValue* locale_config_dict = NULL;
    // Search for a config based on current initial locale.
    if (initial_locales->GetDictionary(initial_locale_,
                                       &locale_config_dict)) {
      locale_config_.reset(new LocaleConfig(locale_config_dict));
    }
  }

  return true;
}

// MobileConfig implementation, private ----------------------------------------

MobileConfig::MobileConfig()
    : CustomizationDocument(kAcceptedConfigVersion),
      initial_locale_(StartupUtils::GetInitialLocale()) {
  LoadConfig();
}

MobileConfig::MobileConfig(const std::string& config,
                           const std::string& initial_locale)
    : CustomizationDocument(kAcceptedConfigVersion),
      initial_locale_(initial_locale) {
  LoadManifestFromString(config);
}

MobileConfig::~MobileConfig() {
  STLDeleteValues(&carriers_);
}

void MobileConfig::LoadConfig() {
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&MobileConfig::ReadConfigInBackground,
                 base::Unretained(this),  // this class is a singleton.
                 base::FilePath(kGlobalCarrierConfigPath),
                 base::FilePath(kLocalCarrierConfigPath)));
}

void MobileConfig::ProcessConfig(const std::string& global_config,
                                 const std::string& local_config) {
  // Global config is mandatory, local config is optional.
  bool global_initialized = false;
  bool local_initialized = true;
  scoped_ptr<base::DictionaryValue> global_config_root;

  if (!global_config.empty()) {
    global_initialized = LoadManifestFromString(global_config);
    // Backup global config root as it might be
    // owerwritten while loading local config.
    global_config_root.reset(root_.release());
  }
  if (!local_config.empty())
    local_initialized = LoadManifestFromString(local_config);

  // Treat any parser errors as fatal.
  if (!global_initialized || !local_initialized) {
    root_.reset(NULL);
    local_config_root_.reset(NULL);
  } else {
    local_config_root_.reset(root_.release());
    root_.reset(global_config_root.release());
  }
}

void MobileConfig::ReadConfigInBackground(
    const base::FilePath& global_config_file,
    const base::FilePath& local_config_file) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  std::string global_config;
  std::string local_config;
  if (!base::ReadFileToString(global_config_file, &global_config)) {
    VLOG(1) << "Failed to load global mobile config from: "
            << global_config_file.value();
  }
  if (!base::ReadFileToString(local_config_file, &local_config)) {
    VLOG(1) << "Failed to load local mobile config from: "
            << local_config_file.value();
  }
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(&MobileConfig::ProcessConfig,
                                     base::Unretained(this),  // singleton.
                                     global_config,
                                     local_config));
}

}  // namespace chromeos
