package de.dfki.lt.weka;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * {@link Config} holds the configuration. It is initialized using a properties
 * file.
 *
 * @author Joerg Steffen, DFKI
 * @version $Id
 */
public final class Config {

  /**
   * Contains the only instance of {@link Config}.
   */
  private static Config config;

  /**
   * Holds the properties object containing the configuration.
   */
  private Properties props;


  /**
   * Creates a new instance of {@link Config}. The configuration file to
   * use is read from {@code config/config.cfg}.
   */
  private Config() {

    this.props = new Properties();
    try {
      this.props.load(new FileInputStream("config/config.cfg"));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }


  /**
   * Returns the only instance of {@link Config}.
   *
   * @return the {@link Config}
   */
  public static Config getInstance() {

    if (null == config) {
      config = new Config();
    }

    return config;
  }


  /**
   * Returns the string value extracted from the property with the given
   * name.
   *
   * @param propName
   *          the property name
   * @return a string property value; {@code null} for unknown properties
   */
  public String getString(String propName) {

    String propVal = this.props.getProperty(propName);
    if (null == propVal) {
      System.err.println(
        "unknown string property " + propName
          + "; returning default value of " + propVal);
    }

    return propVal;
  }


  /**
   * Returns the values extracted from the property with the given name.
   *
   * @param propName
   *          the property name
   * @return a list property value; empty for unknown properties
   */
  public List<String> getList(String propName) {

    List<String> result = new ArrayList<String>();

    String propVal = this.props.getProperty(propName);
    if (null != propVal) {
      String[] vals = propVal.split(",");
      for (int i = 0; i < vals.length; i++) {
        result.add(vals[i].trim());
      }
    }
    else {
      System.err.println(
        "unknown list property " + propName
          + "; returning default value of " + result);
    }

    return result;
  }


  /**
   * Returns the boolean value extracted from the property with the given name;
   * returns {@code true} if the value is "true" or "yes", {@code false}
   * otherwise.
   *
   * @param propName
   *          the property name
   * @return a boolean property value; {@code false} for unknown properties
   */
  public boolean getBoolean(String propName) {

    boolean result = false;

    String propVal = this.props.getProperty(propName);
    if (null != propVal) {
      if (propVal.equalsIgnoreCase("true")
          || propVal.equalsIgnoreCase("yes")) {
        result = true;
      }
      else if (propVal.equalsIgnoreCase("false")
          || propVal.equalsIgnoreCase("no")) {
        result = false;
      }
      else {
        System.err.println(
          "unknown boolean value " + propVal + " for property " + propName
            + "; returning default value of " + result);
      }
    }
    else {
      System.err.println(
        "unknown boolean property " + propName
          + "; returning default value of " + result);
    }

    return result;
  }


  /**
   * Returns the integer value extracted from the property with the given
   * name.
   *
   * @param propName
   *          a {@link String} with the property name
   * @return an {@code int} with the property value; {@code 0} for unknown
   *         properties
   */
  public int getInt(String propName) {

    int result = 0;

    String propVal = this.props.getProperty(propName);
    if (null != propVal) {
      try {
        result = Integer.parseInt(propVal);
      } catch (NumberFormatException e) {
        System.err.println(
          "could not parse int value " + propVal + " for property " + propName
            + "; returning default value of " + result);
      }
    }
    else {
      System.err.println(
        "unknown int property " + propName
          + "; returning default value of " + result);
    }

    return result;
  }


  /**
   * Returns the double value extracted from the property with the given
   * name.
   *
   * @param propName
   *          the property name
   * @return a double property value; {@code 0} for unknown properties
   */
  public double getDouble(String propName) {

    double result = 0.0;

    String propVal = this.props.getProperty(propName);
    if (null != propVal) {
      try {
        result = Double.parseDouble(propVal);
      } catch (NumberFormatException e) {
        System.err.println(
          "could not parse double value " + propVal + " for property "
            + propName + "; returning default value of " + result);
      }
    }
    else {
      System.err.println(
        "unknown double property " + propName
          + "; returning default value of " + result);
    }

    return result;
  }
}
