package yi.util.io.input;

import java.util.*;
import java.awt.Image;
import java.awt.Dimension;
import yi.util.io.ImageReader;
import yi.util.config.*;

public abstract class DIU implements DataInputUnit{
  /**
   * Which format to use for input
   */
  public final static int INPUT_NONE = 0;
  public final static int INPUT_SER  = 1;
  public final static int INPUT_XML  = 2;
  public final static int INPUT_CSV  = 4;
  public final static int INPUT_ALL  = 0xFF;

  /**
   * Name connection character
   */
  public final static char CONNECT_CHAR = '.';
  public final static String DEFAULT_SOURCE_NAME = "default";

  private static DIU m_singleton = null;

  /**
   * It is used to remember whether how many times a INPUT name is used.  When
   * a file name is used to INPUT the first time, a index number "1" is appended
   * to the filename; the second time, "2" is appended...
   */
  protected HashMap m_inputInstances = new HashMap();

  public static String DIU_TYPE = "yi.util.io.input.DIU_Xml";

  protected DIU() {
  }

  public static DIU getSingleton() {
    if (m_singleton != null) return m_singleton;

    // get the data output unit type from Configuration
    DIU_TYPE = Configuration.getStringParameter(
        "DIU_TYPE", DIU_TYPE);
    try {
      Class c = Class.forName(DIU_TYPE);
      m_singleton = (DIU)c.newInstance();
    }
    catch (ClassNotFoundException e) {
      System.err.println("Can't find the data input unit specified");
      e.printStackTrace();
      m_singleton = DIU_Xml.getSingleton();
    }
    catch (Exception e) {
      System.err.println("Not a valid class for data input unit");
      e.printStackTrace();
      m_singleton = DIU_Xml.getSingleton();
    }
    return m_singleton;
  }

  /**
   * Use default data input unit instance to input
   * @param sourceName
   * @param producerName
   * @param dataName
   * @param c
   * @return
   */
  public Object input(String sourceName, String producerName, String dataName, Class c) throws DataInputException{
    return getSingleton().input(sourceName, producerName, dataName, c);
  }

  /**
   * Input the object to user-specified destination (in "where")
   * @param where combination of INPUT_SER and INPUT_XML. INPUT_ALL and
   *              INPUT_NONE are also available
   * @param sourceName
   * @param producerName
   * @param dataName
   * @param obj
   */
  public Object input(int where,
    String sourceName, String producerName, String dataName, Class c)  throws DataInputException{
    if ((where & INPUT_SER) > 0) {
      return DIU_Ser.getSingleton().input(sourceName, producerName, dataName, c);
    }
    if ((where & INPUT_XML) > 0) {
      return DIU_Xml.getSingleton().input(sourceName, producerName, dataName, c);
    }
    if ((where & INPUT_CSV) > 0) {
      return DIU_Csv.getSingleton().input(sourceName, producerName, dataName, c);
    }
    return null;
  }

  public static Object in(int where,
    String producerName, String dataName, Class c)  throws DataInputException{
      String sourceName = Configuration.getStringParameter("SOURCE_NAME", DEFAULT_SOURCE_NAME);
      String destPath = Configuration.getStringParameter("DEST_PATH", "");
      sourceName = destPath + sourceName;
      return getSingleton().input(where, sourceName, producerName, dataName, c);
  }

  public static Object in(int where, String sourceName,
    String producerName, String dataName, Class c)  throws DataInputException{
      return getSingleton().input(where, sourceName, producerName, dataName, c);
  }

  /**
   * When a DIU want to input to a file, it will first see how many time this
   * name is used.  It then append that name with a index number.  The name is
   * 1 based. (the first time, return index 1)
   * @param instanceName
   * @return
   */
  protected String getInstanceName(String instanceName) {
    if (!m_inputInstances.containsKey(instanceName)) {
      m_inputInstances.put(instanceName, new Integer(0));
    }
    Integer index = (Integer)m_inputInstances.get(instanceName);
    index = new Integer(index.intValue() + 1);
    m_inputInstances.put(instanceName, index);
    return instanceName + index;
  }

}