/*
 * 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;
  }

  /**
   * 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<String, String>();
    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;
  }
  
  /**
   * 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);
  }

  /**
   * 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 setRoleOpt(String role, String option, int val) {
    setComponentOpt(role, option, Integer.toString(val));
  }

  
}
