// Copyright (C) 2014 Google Inc.
//
// 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 <libaddressinput/preload_supplier.h>

#include <libaddressinput/address_data.h>
#include <libaddressinput/address_field.h>
#include <libaddressinput/callback.h>
#include <libaddressinput/supplier.h>
#include <libaddressinput/util/basictypes.h>
#include <libaddressinput/util/scoped_ptr.h>

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <functional>
#include <map>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#include "lookup_key.h"
#include "region_data_constants.h"
#include "retriever.h"
#include "rule.h"
#include "util/json.h"
#include "util/string_compare.h"

namespace i18n {
namespace addressinput {

namespace {

// STL predicate less<> that uses StringCompare to match strings that a human
// reader would consider to be "the same". The default implementation just does
// case insensitive string comparison, but StringCompare can be overriden with
// more sophisticated implementations.
class IndexLess : public std::binary_function<std::string, std::string, bool> {
 public:
  result_type operator()(const first_argument_type& a,
                         const second_argument_type& b) const {
    static const StringCompare kStringCompare;
    return kStringCompare.NaturalLess(a, b);
  }
};

}  // namespace

class IndexMap : public std::map<std::string, const Rule*, IndexLess> {};

namespace {

class Helper {
 public:
  // Does not take ownership of its parameters.
  Helper(const std::string& region_code,
         const std::string& key,
         const PreloadSupplier::Callback& loaded,
         const Retriever& retriever,
         std::set<std::string>* pending,
         IndexMap* rule_index,
         std::vector<const Rule*>* rule_storage,
         std::map<std::string, const Rule*>* region_rules)
      : region_code_(region_code),
        loaded_(loaded),
        pending_(pending),
        rule_index_(rule_index),
        rule_storage_(rule_storage),
        region_rules_(region_rules),
        retrieved_(BuildCallback(this, &Helper::OnRetrieved)) {
    assert(pending_ != NULL);
    assert(rule_index_ != NULL);
    assert(rule_storage_ != NULL);
    assert(region_rules_ != NULL);
    assert(retrieved_ != NULL);
    pending_->insert(key);
    retriever.Retrieve(key, *retrieved_);
  }

 private:
  ~Helper() {}

  void OnRetrieved(bool success,
                   const std::string& key,
                   const std::string& data) {
    int rule_count = 0;

    size_t status = pending_->erase(key);
    assert(status == 1);  // There will always be one item erased from the set.
    (void)status;  // Prevent unused variable if assert() is optimized away.

    Json json;
    std::string id;
    std::vector<const Rule*> sub_rules;

    IndexMap::iterator last_index_it = rule_index_->end();
    IndexMap::iterator last_latin_it = rule_index_->end();
    std::map<std::string, const Rule*>::iterator last_region_it =
        region_rules_->end();

    IndexMap::const_iterator hints[arraysize(LookupKey::kHierarchy) - 1];
    std::fill(hints, hints + arraysize(hints), rule_index_->end());

    if (!success) {
      goto callback;
    }

    if (!json.ParseObject(data)) {
      success = false;
      goto callback;
    }

    for (std::vector<const Json*>::const_iterator
         it = json.GetSubDictionaries().begin();
         it != json.GetSubDictionaries().end();
         ++it) {
      const Json* value = *it;
      assert(value != NULL);
      if (!value->GetStringValueForKey("id", &id)) {
        success = false;
        goto callback;
      }
      assert(!id.empty());

      size_t depth = std::count(id.begin(), id.end(), '/') - 1;
      assert(depth < arraysize(LookupKey::kHierarchy));
      AddressField field = LookupKey::kHierarchy[depth];

      Rule* rule = new Rule;
      if (field == COUNTRY) {
        // All rules on the COUNTRY level inherit from the default rule.
        rule->CopyFrom(Rule::GetDefault());
      }
      rule->ParseJsonRule(*value);
      assert(id == rule->GetId());  // Sanity check.

      rule_storage_->push_back(rule);
      if (depth > 0) {
        sub_rules.push_back(rule);
      }

      // Add the ID of this Rule object to the rule index with natural string
      // comparison for keys.
      last_index_it =
          rule_index_->insert(last_index_it, std::make_pair(id, rule));

      // Add the ID of this Rule object to the region-specific rule index with
      // exact string comparison for keys.
      last_region_it =
          region_rules_->insert(last_region_it, std::make_pair(id, rule));

      ++rule_count;
    }

    /*
     * Normally the address metadata server takes care of mapping from natural
     * language names to metadata IDs (eg. "São Paulo" -> "SP") and from Latin
     * script names to local script names (eg. "Tokushima" -> "徳島県").
     *
     * As the PreloadSupplier doesn't contact the metadata server upon each
     * Supply() request, it instead has an internal lookup table (rule_index_)
     * that contains such mappings.
     *
     * This lookup table is populated by iterating over all sub rules and for
     * each of them construct ID strings using human readable names (eg. "São
     * Paulo") and using Latin script names (eg. "Tokushima").
     */
    for (std::vector<const Rule*>::const_iterator
         it = sub_rules.begin(); it != sub_rules.end(); ++it) {
      std::stack<const Rule*> hierarchy;
      hierarchy.push(*it);

      // Push pointers to all parent Rule objects onto the hierarchy stack.
      for (std::string parent_id((*it)->GetId());;) {
        // Strip the last part of parent_id. Break if COUNTRY level is reached.
        std::string::size_type pos = parent_id.rfind('/');
        if (pos == sizeof "data/ZZ" - 1) {
          break;
        }
        parent_id.resize(pos);

        IndexMap::const_iterator* const hint = &hints[hierarchy.size() - 1];
        if (*hint == rule_index_->end() || (*hint)->first != parent_id) {
          *hint = rule_index_->find(parent_id);
        }
        assert(*hint != rule_index_->end());
        hierarchy.push((*hint)->second);
      }

      std::string human_id((*it)->GetId().substr(0, sizeof "data/ZZ" - 1));
      std::string latin_id(human_id);

      // Append the names from all Rule objects on the hierarchy stack.
      for (; !hierarchy.empty(); hierarchy.pop()) {
        const Rule* rule = hierarchy.top();

        human_id.push_back('/');
        if (!rule->GetName().empty()) {
          human_id.append(rule->GetName());
        } else {
          // If the "name" field is empty, the name is the last part of the ID.
          const std::string& id = rule->GetId();
          std::string::size_type pos = id.rfind('/');
          assert(pos != std::string::npos);
          human_id.append(id.substr(pos + 1));
        }

        if (!rule->GetLatinName().empty()) {
          latin_id.push_back('/');
          latin_id.append(rule->GetLatinName());
        }
      }

      // If the ID has a language tag, copy it.
      {
        const std::string& id = (*it)->GetId();
        std::string::size_type pos = id.rfind("--");
        if (pos != std::string::npos) {
          human_id.append(id, pos, id.size() - pos);
        }
      }

      last_index_it =
          rule_index_->insert(last_index_it, std::make_pair(human_id, *it));

      // Add the Latin script ID, if a Latin script name could be found for
      // every part of the ID.
      if (std::count(human_id.begin(), human_id.end(), '/') ==
          std::count(latin_id.begin(), latin_id.end(), '/')) {
        last_latin_it =
            rule_index_->insert(last_latin_it, std::make_pair(latin_id, *it));
      }
    }

  callback:
    loaded_(success, region_code_, rule_count);
    delete this;
  }

  const std::string region_code_;
  const PreloadSupplier::Callback& loaded_;
  std::set<std::string>* const pending_;
  IndexMap* const rule_index_;
  std::vector<const Rule*>* const rule_storage_;
  std::map<std::string, const Rule*>* const region_rules_;
  const scoped_ptr<const Retriever::Callback> retrieved_;

  DISALLOW_COPY_AND_ASSIGN(Helper);
};

std::string KeyFromRegionCode(const std::string& region_code) {
  AddressData address;
  address.region_code = region_code;
  LookupKey lookup_key;
  lookup_key.FromAddress(address);
  return lookup_key.ToKeyString(0);  // Zero depth = COUNTRY level.
}

}  // namespace

PreloadSupplier::PreloadSupplier(const std::string& validation_data_url,
                                 const Downloader* downloader,
                                 Storage* storage)
    : retriever_(new Retriever(validation_data_url, downloader, storage)),
      pending_(),
      rule_index_(new IndexMap),
      rule_storage_(),
      region_rules_() {}

PreloadSupplier::~PreloadSupplier() {
  for (std::vector<const Rule*>::const_iterator
       it = rule_storage_.begin(); it != rule_storage_.end(); ++it) {
    delete *it;
  }
}

void PreloadSupplier::Supply(const LookupKey& lookup_key,
                             const Supplier::Callback& supplied) {
  Supplier::RuleHierarchy hierarchy;
  bool success = GetRuleHierarchy(lookup_key, &hierarchy);
  supplied(success, lookup_key, hierarchy);
}

const Rule* PreloadSupplier::GetRule(const LookupKey& lookup_key) const {
  assert(IsLoaded(lookup_key.GetRegionCode()));
  Supplier::RuleHierarchy hierarchy;
  if (!GetRuleHierarchy(lookup_key, &hierarchy)) {
    return NULL;
  }
  return hierarchy.rule[lookup_key.GetDepth()];
}

void PreloadSupplier::LoadRules(const std::string& region_code,
                                const Callback& loaded) {
  const std::string& key = KeyFromRegionCode(region_code);

  if (IsLoadedKey(key)) {
    loaded(true, region_code, 0);
    return;
  }

  if (IsPendingKey(key)) {
    return;
  }

  new Helper(
      region_code,
      key,
      loaded,
      *retriever_,
      &pending_,
      rule_index_.get(),
      &rule_storage_,
      &region_rules_[region_code]);
}

const std::map<std::string, const Rule*>& PreloadSupplier::GetRulesForRegion(
    const std::string& region_code) const {
  assert(IsLoaded(region_code));
  return region_rules_.find(region_code)->second;
}

bool PreloadSupplier::IsLoaded(const std::string& region_code) const {
  return IsLoadedKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::IsPending(const std::string& region_code) const {
  return IsPendingKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::GetRuleHierarchy(const LookupKey& lookup_key,
                                       RuleHierarchy* hierarchy) const {
  assert(hierarchy != NULL);

  if (RegionDataConstants::IsSupported(lookup_key.GetRegionCode())) {
    size_t max_depth = std::min(
        lookup_key.GetDepth(),
        RegionDataConstants::GetMaxLookupKeyDepth(lookup_key.GetRegionCode()));

    for (size_t depth = 0; depth <= max_depth; ++depth) {
      const std::string& key = lookup_key.ToKeyString(depth);
      IndexMap::const_iterator it = rule_index_->find(key);
      if (it == rule_index_->end()) {
        return depth > 0;  // No data on COUNTRY level is failure.
      }
      hierarchy->rule[depth] = it->second;
    }
  }

  return true;
}

bool PreloadSupplier::IsLoadedKey(const std::string& key) const {
  return rule_index_->find(key) != rule_index_->end();
}

bool PreloadSupplier::IsPendingKey(const std::string& key) const {
  return pending_.find(key) != pending_.end();
}

}  // namespace addressinput
}  // namespace i18n
