text: //
  // Copyright RIME Developers
  // Distributed under the BSD License
  //
  // 2012-02-26 GONG Chen <chen.sst@gmail.com>
  //
  #include <boost/algorithm/string.hpp>
  #include <boost/filesystem.hpp>
  #include <rime/config.h>
  #include <rime/deployer.h>
  #include <rime/signature.h>
  #include <rime/lever/custom_settings.h>
  #include <Windows.h>
  
  namespace fs = boost::filesystem;
  
  namespace rime {
  
  static string remove_suffix(const string& input, const string& suffix) {
    return boost::ends_with(input, suffix) ?
        input.substr(0, input.length() - suffix.length()) : input;
  }
  
  static string custom_config_file(const string& config_id) {
    return remove_suffix(config_id, ".schema") + ".custom.yaml";
  }
  
  CustomSettings::CustomSettings(Deployer* deployer,
                                 const string& config_id,
                                 const string& generator_id)
      : deployer_(deployer),
        config_id_(config_id),
        generator_id_(generator_id) {
  }
  
  bool CustomSettings::Load() {
  
  	//User_Build
  	fs::path config_path = fs::path(deployer_->staging_dir) / (config_id_ + ".yaml");
  	if (!config_.LoadFromFile(config_path.string())) {
  		//Prebuild
  		config_path = fs::path(deployer_->prebuilt_data_dir) / (config_id_ + ".yaml");
  		if (!config_.LoadFromFile(config_path.string())) {
  			LOG(WARNING) << "cannot find '" << config_id_ << ".yaml'.";
  			return false;
  		}
  	}
  	//Custom
  	fs::path custom_config_path = fs::path(deployer_->user_data_dir) / custom_config_file(config_id_);
  	custom_config_.LoadFromFile(custom_config_path.string());
  
  	modified_ = false;
  	return true;
  }
  
  bool CustomSettings::Save() {
    if (!modified_)
      return false;
    Signature signature(generator_id_, "customization");
    signature.Sign(&custom_config_, deployer_);
    fs::path custom_config_path(deployer_->user_data_dir);
    custom_config_path /= custom_config_file(config_id_);
    custom_config_.SaveToFile(custom_config_path.string());
    modified_ = false;
    return true;
  }
  
  an<ConfigValue> CustomSettings::GetValue(const string& key) {
    return config_.GetValue(key);
  }
  
  an<ConfigList> CustomSettings::GetList(const string& key) {
    return config_.GetList(key);
  }
  
  an<ConfigMap> CustomSettings::GetMap(const string& key) {
    return config_.GetMap(key);
  }
  
  bool CustomSettings::Customize(const string& key,
                                 const an<ConfigItem>& item) {
    auto patch = custom_config_.GetMap("patch");
    if (!patch) {
      patch = New<ConfigMap>();
    }
    patch->Set(key, item);
    // the branch 'patch' should be set as a whole in order to be saved, for
    // its sub-key may contain slashes which disables directly setting a sub-item
    custom_config_.SetItem("patch", patch);
    modified_ = true;
    return true;
  }
  
  bool CustomSettings::IsFirstRun() {
    fs::path custom_config_path(deployer_->user_data_dir);
    custom_config_path /= custom_config_file(config_id_);
    Config config;
    if (!config.LoadFromFile(custom_config_path.string()))
      return true;
    return !config.GetMap("customization");
  }
  
  }  // namespace rime
  