/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package org.apache.slider.core.conf;

import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.exceptions.BadConfigException;
import org.apache.slider.core.persist.ConfTreeSerDeser;
import org.apache.slider.core.persist.PersistKeys;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.JsonMappingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ConfTreeOperations {

  public final ConfTree confTree;
  private final MapOperations globalOptions;

  protected static final Logger
    log = LoggerFactory.getLogger(ConfTreeOperations.class);


  public ConfTreeOperations(ConfTree confTree) {
    assert confTree != null : "null tree";
    assert confTree.components != null : "null tree components";
    this.confTree = confTree;
    globalOptions = new MapOperations("global", confTree.global);
  }

  /**
   * Get the underlying conf tree
   * @return the tree
   */
  public ConfTree getConfTree() {
    return confTree;
  }

  /**
   * Validate the configuration
   * @throws BadConfigException
   */
  public void validate() throws BadConfigException {
    validate(null);
  }

  /**
   * Validate the configuration
   * @param validator a provided properties validator
   * @throws BadConfigException
   */
  public void validate(InputPropertiesValidator validator) throws BadConfigException {
    String version = confTree.schema;
    if (version == null) {
      throw new BadConfigException("'version' undefined");
    }
    if (!PersistKeys.SCHEMA.equals(version)) {
      throw new BadConfigException(
          "version %s incompatible with supported version %s",
          version,
          PersistKeys.SCHEMA);
    }
    if (validator != null) {
      validator.validate(this);
    }
  }

  /**
   * Resolve a ConfTree by mapping all global options into each component
   * -if there is none there already
   */
  public void resolve() {
    for (Map.Entry<String, Map<String, String>> comp : confTree.components.entrySet()) {
      mergeInGlobal(comp.getValue());
    }
  }

  /**
   * Merge any options
   * @param component dest values
   */
  public void mergeInGlobal(Map<String, String> component) {
    SliderUtils.mergeMapsIgnoreDuplicateKeys(component, confTree.global);
  }

  /**
   * Get operations on the global set
   * @return a wrapped map
   */
  public MapOperations getGlobalOptions() {
    return globalOptions;
  }


  /**
   * look up a component and return its options
   * @param component component name
   * @return component mapping or null
   */
  public MapOperations getComponent(String component) {
    Map<String, String> instance = confTree.components.get(component);
    if (instance != null) {
      return new MapOperations(component, instance);
    }
    return null;
  }

  /**
   * look up a component and return its options with the specified replacements
   * @param component component name
   * @param replacementOptions replacement options
   * @return component mapping or null
   */
  public MapOperations getComponent(String component, Map<String,String>
      replacementOptions) {
    Map<String, String> instance = confTree.components.get(component);
    if (instance != null) {
      Map<String, String> newInstance = new HashMap<>();
      newInstance.putAll(instance);
      newInstance.putAll(replacementOptions);
      return new MapOperations(component, newInstance);
    }
    return null;
  }

  /**
   * Get at the underlying component map
   * @return a map of components. This is the raw ConfTree data structure
   */
  public Map<String, Map<String, String>> getComponents() {
    return confTree.components;
  }

  /**
   * Get a component -adding it to the components map if
   * none with that name exists
   * @param name role
   * @return role mapping
   */
  public MapOperations getOrAddComponent(String name) {
    MapOperations operations = getComponent(name);
    if (operations != null) {
      return operations;
    }
    //create a new instances
    Map<String, String> map = new HashMap<>();
    confTree.components.put(name, map);
    return new MapOperations(name, map);
  }


  /*
   * return the Set of names names
   */
  @JsonIgnore
  public Set<String> getComponentNames() {
    return new HashSet<String>(confTree.components.keySet());
  }
  
  

  /**
   * Get a component whose presence is mandatory
   * @param name component name
   * @return the mapping
   * @throws BadConfigException if the name is not there
   */
  public MapOperations getMandatoryComponent(String name) throws
                                                          BadConfigException {
    MapOperations ops = getComponent(name);
    if (ops == null) {
      throw new BadConfigException("Missing component " + name);
    }
    return ops;
  }

  /**
   * Set a global option, converting it to a string as needed
   * @param key key
   * @param value non null value
   */
  public void set(String key, Object value) {
    globalOptions.put(key, value.toString());
  }
  /**
   * get a global option
   * @param key key
   * @return value or null
   * 
   */
  public String get(String key) {
    return globalOptions.get(key);
  }

  /**
   * Propagate all global keys matching a prefix
   * @param src source
   * @param prefix prefix
   */
  public void propagateGlobalKeys(ConfTree src, String prefix) {
    Map<String, String> global = src.global;
    for (Map.Entry<String, String> entry : global.entrySet()) {
      String key = entry.getKey();
      if (key.startsWith(prefix)) {
        set(key, entry.getValue());
      }
    }
  }

  /**
   * Propagate all global keys matching a prefix
   * @param src source
   * @param prefix prefix
   */
  public void propagateGlobalKeys(ConfTreeOperations src, String prefix) {
    propagateGlobalKeys(src.confTree, prefix);
  }

  /**
   * Merge the map of a single component
   * @param component component name
   * @param map map to merge
   */
  public void mergeSingleComponentMap(String component, Map<String, String> map) {
    MapOperations comp = getOrAddComponent(component);
    comp.putAll(map);
  }
  /**
   * Merge the map of a single component
   * @param component component name
   * @param map map to merge
   */
  public void mergeSingleComponentMapPrefix(String component,
                                            Map<String, String> map,
                                            String prefix,
                                            boolean overwrite) {
    MapOperations comp = getOrAddComponent(component);
    comp.mergeMapPrefixedKeys(map,prefix, overwrite);
  }

  /**
   * Merge in components
   * @param commandOptions component options on the CLI
   */
  public void mergeComponents(Map<String, Map<String, String>> commandOptions) {
    for (Map.Entry<String, Map<String, String>> entry : commandOptions.entrySet()) {
      mergeSingleComponentMap(entry.getKey(), entry.getValue());
    }
  }

  /**
   * Merge in components
   * @param commandOptions component options on the CLI
   */
  public void mergeComponentsPrefix(Map<String,
    Map<String, String>> commandOptions,
                                    String prefix,
                                    boolean overwrite) {
    for (Map.Entry<String, Map<String, String>> entry : commandOptions.entrySet()) {
      mergeSingleComponentMapPrefix(entry.getKey(), entry.getValue(), prefix, overwrite);
    }
  }

  /**
   * Merge in another tree -no overwrites of global or conf data
   * (note that metadata does a naive putAll merge/overwrite)
   * @param that the other tree
   */
  public void mergeWithoutOverwrite(ConfTree that) {

    getGlobalOptions().mergeWithoutOverwrite(that.global);
    confTree.metadata.putAll(that.metadata);
    confTree.credentials.putAll(that.credentials);

    for (Map.Entry<String, Map<String, String>> entry : that.components.entrySet()) {
      MapOperations comp = getOrAddComponent(entry.getKey());
      comp.mergeWithoutOverwrite(entry.getValue());
    }
  }
  
  /**
   * Merge in another tree with overwrites
   * @param that the other tree
   */
  public void merge(ConfTree that) {

    getGlobalOptions().putAll(that.global);
    confTree.metadata.putAll(that.metadata);
    confTree.credentials.putAll(that.credentials);

    for (Map.Entry<String, Map<String, String>> entry : that.components.entrySet()) {
      MapOperations comp = getOrAddComponent(entry.getKey());
      comp.putAll(entry.getValue());
    }
  }

  
  /**
   * Load from a resource. The inner conf tree is the loaded data -unresolved
   * @param resource resource
   * @return loaded value
   * @throws IOException load failure
   */
  public static ConfTreeOperations fromResource(String resource) throws
                                                                 IOException {
    ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
    ConfTreeOperations ops = new ConfTreeOperations(
       confTreeSerDeser.fromResource(resource) );
    return ops;      
  }
  
  /**
   * Load from a resource. The inner conf tree is the loaded data -unresolved
   * @param resource resource
   * @return loaded value
   * @throws IOException load failure
   */
  public static ConfTreeOperations fromFile(File resource) throws
                                                                 IOException {
    ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
    ConfTreeOperations ops = new ConfTreeOperations(
       confTreeSerDeser.fromFile(resource) );
    return ops;
  }

  /**
   * Load from a json String. The inner conf tree is the loaded data -unresolved
   * @param json json string
   * @return loaded value
   * @throws IOException load failure
   */
  public static ConfTreeOperations fromString(String json) throws
      IOException {
    ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
    ConfTreeOperations ops = new ConfTreeOperations(
        confTreeSerDeser.fromJson(json) );
    return ops;
  }

  /**
   * Build from an existing instance -which is cloned via JSON ser/deser
   * @param instance the source instance
   * @return loaded value
   * @throws IOException load failure
   */
  public static ConfTreeOperations fromInstance(ConfTree instance) throws
                                                                 IOException {
    ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
    ConfTreeOperations ops = new ConfTreeOperations(
       confTreeSerDeser.fromJson(confTreeSerDeser.toJson(instance)) );
    return ops;
  }

  /**
   * Load from a file and merge it in
   * @param file file
   * @throws IOException any IO problem
   * @throws BadConfigException if the file is invalid
   */
  public void mergeFile(File file) throws IOException, BadConfigException {
    mergeFile(file, null);
  }

  /**
   * Load from a file and merge it in
   * @param file file
   * @param validator properties validator
   * @throws IOException any IO problem
   * @throws BadConfigException if the file is invalid
   */
  public void mergeFile(File file, InputPropertiesValidator validator) throws IOException, BadConfigException {
    ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
    ConfTree tree = confTreeSerDeser.fromFile(file);
    ConfTreeOperations ops = new ConfTreeOperations(tree);
    ops.validate(validator);
    merge(ops.confTree);
  }

  @Override
  public String toString() {
    return confTree.toString();
  }

  /**
   * Convert to a JSON string
   * @return a JSON string description
   */
  public String toJson() throws IOException,
                                JsonGenerationException,
                                JsonMappingException {
    return confTree.toJson();
  }

  /**
   * Get a component option
   * @param name component name
   * @param option option name
   * @param defVal default value
   * @return resolved value
   */
  public String getComponentOpt(String name, String option, String defVal) {
    MapOperations roleopts = getComponent(name);
    if (roleopts == null) {
      return defVal;
    }
    return roleopts.getOption(option, defVal);
  }

  /**
   * Get a component opt; use {@link Integer#decode(String)} so as to take hex
   * oct and bin values too.
   *
   * @param name component name
   * @param option option name
   * @param defVal default value
   * @return parsed value
   * @throws NumberFormatException if the role could not be parsed.
   */
  public int getComponentOptInt(String name, String option, int defVal) {
    String val = getComponentOpt(name, option, Integer.toString(defVal));
    return Integer.decode(val);
  }

  /**
   * Get a component opt as a boolean using {@link Boolean#valueOf(String)}.
   *
   * @param name component name
   * @param option option name
   * @param defVal default value
   * @return parsed value
   * @throws NumberFormatException if the role could not be parsed.
   */
  public boolean getComponentOptBool(String name, String option, boolean defVal) {
    String val = getComponentOpt(name, option, Boolean.toString(defVal));
    return Boolean.valueOf(val);
  }

  /**
   * Set a component option, creating the component if necessary
   * @param component component name
   * @param option option name
   * @param val value
   */
  public void setComponentOpt(String component, String option, String val) {
    Map<String, String> roleopts = getOrAddComponent(component);
    roleopts.put(option, val);
  }

  /**
   * Set an integer role option, creating the role if necessary
   * @param role role name
   * @param option option name
   * @param val integer value
   */
  public void setComponentOpt(String role, String option, int val) {
    setComponentOpt(role, option, Integer.toString(val));
  }
  /**
   * Set a long role option, creating the role if necessary
   * @param role role name
   * @param option option name
   * @param val long value
   */
  public void setComponentOpt(String role, String option, long val) {
    setComponentOpt(role, option, Long.toString(val));
  }

}
