import java.io.*;
import com.medcosm.primitives.GraphData;
import com.medcosm.datalogger.ImporterInterface;
import java.util.GregorianCalendar;
import java.util.Date;
import java.text.SimpleDateFormat;

/**
 * This class is interpreted dynamically at run-time in the MedCosm DataLogger.
 * This is a *very* flexible mechanism allowing importing virtually any type of data
 * to the server in a simple fashion.  Note that you simply leave this importer
 * class (with the ".java" extension) in the same directory as the DataLogger.jar
 * and it will be executed at run-time.  Do not compile it!
 *
 * Using the importer file mechanism, you can convert a data file (as in this example),
 * collect your data from around the web, sample a device with a Java API.  This particular
 * example reads electric power (Watts) from a solar array and build the necessary
 * GraphData structure for upload to the MedCosm DataLogger.
 *
 * <p>Title: DataLogger</p>
 * <p>Description: Generic Data Logging Package</p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: MedCosm</p>
 * @author Alan Stein
 * @version 1.0
 */
class WinverterChannelImporter implements ImporterInterface
{
  /**
   * "readData" is the only required method in the Importer class.  It reads data
   * and builds the "GraphData" data structure when called.
   *
   * GraphData usage is as follows:
   *
   * GraphData graphData=new GraphData();
   * graphData.addVal(double yValue0, String comment0);   //add a data point, let system autonumber the X-axis values
   * graphData.addVal(double yValue1, String comment1);
   *  ...
   *
   * or
   *
   * GraphData graphData=new GraphData();
   * graphData.addVal(int xValue0, double yValue0, String comment0);  //add a data point, explicitly set the X-value
   * graphData.addVal(int xValue1, double yValue1, String comment1);
   *  ...
   *
   * @param fileName filename to read
   * @return GraphData object
   */
  GraphData readData(String fileName)
  {
    GraphData graphData=new GraphData();

    System.out.println("Opening File:  "+fileName);
    File f=new File(fileName);
    BufferedReader bf = null;
    bf = new BufferedReader(new FileReader(f));
    GregorianCalendar gcStart;

    int lineNum=0;

     try
     {
       boolean eof;
       String line;
       do
       {
         line = bf.readLine();
         System.out.println("Read line:  "+line);

         if (line != null)
         {
           lineNum++;
           eof = false;

           if(lineNum==1)
           {
             String[] csv=parseCSVline(line);
             graphData.setDescription(csv[0]);

             SimpleDateFormat sdFormat=new SimpleDateFormat("MM/dd/yy hh:mm:ss aa");

             System.out.println("Line data:  "+csv[0]);

             Date date;

             try
             {
                 // Parse the text version of the date.
                 // We have to perform the parse method in a
                 // try-catch construct in case dateStringToParse
                 // does not contain a date in the format we are expecting.
                 date = sdFormat.parse(csv[0]);
                 // Now send the parsed date as a long value
                 // to the system output.
//                 System.out.println(date.getTime());
             }
             catch(Exception ex)
             {
               ex.printStackTrace();
               System.exit(0);
             }

             gcStart=new GregorianCalendar();
             gcStart.setTime(date);
             gcStart.add(GregorianCalendar.HOUR, -168); //channel should have 168 hours of data

             System.out.println("Starting Date is "+formatCalendarToLong(gcStart));
           }
           else
           if(lineNum==2)
           {
             graphData.setDescription(parseCSVline(line)[0]+" as of "+graphData.getDescription());
           }
           else
           if(lineNum>=6)
           {
             String[] csv=parseCSVline(line);
             if(csv.length==4)
             {
//               graphData.addVal(-new Float(csv[3]).floatValue(), ""); //don't explicitly set ordinate, will use index between 0-167

               int tmpLine=lineNum-5;
//               System.out.println("Line="+tmpLine);
               GregorianCalendar tmpGC=gcStart.clone();
               tmpGC.add(GregorianCalendar.HOUR, tmpLine);  //increment start date + num hours offset (0-167)
               long ord=formatCalendarToLong(tmpGC);
               graphData.addVal(ord , -new Float(csv[3]).floatValue(), "");   //explicitly set ordinate with correct date
             }
           }
         }
         else
         {
           eof = true;
         }
       }
       while (!eof);

     System.out.println("Number of Lines Read:  "+lineNum);

    graphData.debug(); //debug

     return graphData;
    }
    catch (FileNotFoundException ex)
    {
      ex.printStackTrace();
      return null;
    }
  }


  /**
   * format a calendar date to a long per the MedCosm DataLogger.
   * eg, "YYYYMMDDhhmm"
   * @param gc Calendar date to be formatted
   * @return value for use with MedCosm DataLogger
   */
  private long formatCalendarToLong(GregorianCalendar gc)
  {
    String timeStampStr=""+gc.get(GregorianCalendar.YEAR);
    timeStampStr=timeStampStr+zeroPad(gc.get(GregorianCalendar.MONTH)+1,2);
    timeStampStr=timeStampStr+zeroPad(gc.get(GregorianCalendar.DATE),2);
    timeStampStr=timeStampStr+zeroPad(gc.get(GregorianCalendar.HOUR_OF_DAY),2);
    timeStampStr=timeStampStr+zeroPad(gc.get(GregorianCalendar.MINUTE),2);

    long tStamp=Long.parseLong(timeStampStr);

    return tStamp;
  }


  /**
   * Parse a comma serparated value (aka CSV, comma delimited) line into separate strings, strip out double-quote chars
   * @param line string to be parsed
   * @return array of strings
   */
  private String[] parseCSVline(String line)
  {
    Vector retVals=new Vector();

    StringTokenizer st=new StringTokenizer(line, ",");

    while (st.hasMoreTokens())
    {
      retVals.add(st.nextToken());
    }

    String[] retStrArr=new String[retVals.size()];

    for (int i = 0; i < retStrArr.length; i++)
    {
      retStrArr[i]=(String)retVals.elementAt(i);
      retStrArr[i]=retStrArr[i].replace('\"',' '); //strip out any quote chars
    }

    return retStrArr;
  }


  /**
   * Routine to pad an integer string with zeroes to left of value
   * @param value integer value to be padded
   * @param charLength length of return string
   * @return string of integer value, left-padded with zeroes
   */
  String zeroPad(int value, int charLength)
  {
    String retStr=String.valueOf(value);
    retStr=new String("0000000000000000").substring(0,charLength-retStr.length())+retStr;
    return retStr;
  }



}
