package evaluator.util;


import java.io.File;


/**
 * class ExperimentOutput
 * <p>Description: Handles the output operations for the Evaluator. Early
 * flushing preferred..</p>
 * <p>Copyright: Copyright (C) 2003</p>
 * <p>Company: University of Hamburg, Germany</p>
 * @author Hartmut Obendorf, http://asi-www.informatik.uni-hamburg.de/personen/obendorf/
 * @author Harald Weinreich, http://vsis-www.informatik.uni-hamburg.de/~weinreic/
 * @version 1.0
 */

public class ExperimentOutputWriter {
    private static final String FILEDIR = "log/experiment-output";
    private static final String SUBJNAME = "sub";
    private static final String EXPRNAME = "exp";

    // class variables
    private String                      _filename;
    private java.io.OutputStreamWriter  _outputStreamWriter;
    private boolean                     _fileIsOpen;

    /**
     * This class has no default constructor, the participant's number and an
     * additional experiment index for experiment series must be given.
     * @param participantNumber number of the participant
     * @param experimentIndex   index of the experiment
     */
    public ExperimentOutputWriter(long participantNumber, long experimentIndex) {
        File outputFile;

        _filename = FILEDIR + File.separator + SUBJNAME + participantNumber
                + "_" + EXPRNAME + experimentIndex;

        checkOrCreateDirectory();

        outputFile = new File(_filename);
        if (outputFile.exists()) {
            File            backupFile;
            int             index = 0;

            do {
                backupFile = new File(outputFile.getPath() + ".bak" + Integer.toString(index));
                index++;
            } while (backupFile.exists());

            outputFile.renameTo(backupFile);
        }

        try {
            _outputStreamWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outputFile));
        } catch (java.io.FileNotFoundException fofe) {
            System.err.println(fofe.toString());
            System.exit(-1);
        }

        _fileIsOpen = true;
    }

    public int close() {
        if (_fileIsOpen) {
            try {
                _outputStreamWriter.close();
            } catch (java.io.IOException ioexception) {
                System.err.println(ioexception.toString());
                return -1;
            }
            _fileIsOpen = false;
        }

        return 0;
    }

    /**
     * Write string to output file. Format: <PRE>&lt;string&gt;</PRE>
     * @param string to write
     * @return 0 (success) or -1 (IO Error)
     */
    public int write(String string) {
        try {
            _outputStreamWriter.write(string + "\r\n");
            _outputStreamWriter.flush();
        } catch (java.io.IOException ioexception) {
            System.err.println(ioexception.toString());
            return -1;
        }
        return 0;
    }

    /**
     * Write dataSource data to output file. Can write more than one
     * datum, depending on dataSource.hasMoreData().
     * Format: <PRE>&lt;header&gt;;&lt;timestamp&gt;</PRE>
     * @param dataSource object supplying data to write
     * @return 0 (success) or -1 (IO Error)
     */
    public int write(evaluator.util.DataSourceInterface dataSource) {
        if (dataSource == null) {
            return -1;
        }
    
        try {
            while (dataSource.hasMoreData()) {
                _outputStreamWriter.write(dataSource.getHeader() + ";");
                _outputStreamWriter.write(dataSource.getData() + "\r\n");
                dataSource.next();
            }
            _outputStreamWriter.flush();
        } catch (java.io.IOException ioexception) {
            System.err.println(ioexception.toString());
            return -1;
        }
        return 0;
    }

    /**
     * Write timestamp to output file. Format: <PRE>TIME;&lt;timestamp&gt;</PRE>
     * @param timestamp time in ms
     * @return 0 (success) or -1 (IO Error)
     */
    public int write(Long timestamp) {
        try {
            _outputStreamWriter.write("TIME;" + timestamp.toString() + "\r\n");
            _outputStreamWriter.flush();
        } catch (java.io.IOException ioexception) {
            System.err.println(ioexception.toString());
            return -1;
        }
        return 0;
    }

    /**
     * Test if directory for output Data exists:
     */
    private static void checkOrCreateDirectory() {
        File dataDirectory = new File(FILEDIR);

        if (!dataDirectory.exists()) {  // No: Create!
            System.out.println("\nData direcotry \"" + FILEDIR + "\" missing!");
            System.out.print("Creating Directory...");
            if (dataDirectory.mkdir()) {
                System.out.println("OK");
            } else {
                System.out.println("ERROR!");
            }
        } else if (!dataDirectory.isDirectory()) {  // Test if OK
            System.out.println("Error!!! " + FILEDIR + " is no directory!"); 
        }
    }

    public static long getNextParticipantNumber(long experimentIndex) {
        File         testFile;
        String       testFilename;
        int          participant = 0;
        boolean      keepLooking = true;

        checkOrCreateDirectory();

        while (keepLooking) {
            testFilename = FILEDIR + File.separator + SUBJNAME + participant
                    + "_" + EXPRNAME + experimentIndex;

            testFile = new File(testFilename);

            if (testFile.exists()) {
                participant++;
            } else {
                keepLooking = false;
            }
        }

        return participant;
    }
}
