package com.fujitsu.iflowqa.testframe;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Hashtable;
import java.util.Properties;


public class CollectedFlowPathTests implements TestSet {

    private TestRecorder tr;
    private TestRecorderText trt;

    private Properties serverProperties;
    private TestSet xt;
    private String ignoreError = "false";
    private String[] commandLineArgs = null;
    private Hashtable excludeList = null;
    /*
     * Zero argument constructor.
     */
    public CollectedFlowPathTests()
    {
        xt = new FlowPath();
    }

    /*
     * This method runs the test.
     */
    public void runTests(TestRecorder nRecorder)
        throws Exception
    {
        tr = nRecorder;
        trt = null;
        if (tr instanceof TestRecorderText) {
            trt = (TestRecorderText) tr;
        }
        else {
            tr.log("NOT a TestRecorderText .... how can this be?");
        }

        //start with a clean exclude list every invocation
        excludeList = new Hashtable();

        commandLineArgs = tr.getCommandLineArgs();
        if (commandLineArgs.length < 3) {
            throw new Exception("CollectedFlowPathTests requires (1) the path to the directory that holds all the XPDL tests (2) exclude path file (3) voting/novote");
        }
        String startDirectory = commandLineArgs[1];
        if (startDirectory.endsWith("/")) {
            startDirectory = startDirectory.substring(0, startDirectory.length());
        }

        tr.log("Collected tests in directory: "+startDirectory);

        xt = new FlowPath();
        if (commandLineArgs.length > 2) {
            String testType = commandLineArgs[2];
            if(testType.equalsIgnoreCase("voting")) {
                xt = new VotingXPDLTest();
                tr.log("This is a voting test.");
            }
        }

        //to read the list of directories that are to be excluded
        if (commandLineArgs.length > 3) {
            readExcludingDirectoryListFile(commandLineArgs[3]);
        }

        findAndRunFiles(startDirectory);
    }


    /*
     * This method finds the XPDLs in directories and runs them.
     */
    private
    void
    findAndRunFiles(String directoryName)
        throws Exception
    {
        ignoreError = tr.getProperty("IgnoreError", "false");
        if (excludeList.get(directoryName)!=null) {
            tr.log("Excluding "+directoryName);
            return;
        }
        String fullName = tr.getTestDir()+directoryName;
        File dirFile = new File(tr.getTestDir()+directoryName);

        if (!dirFile.exists()) {
            checkTestDir();
            throw new Exception("Test path does not exist: "+dirFile.getName());
        }
        if (dirFile.isDirectory()) {

            tr.log("Checking directory: "+fullName);
            String[] children = dirFile.list();
            int last = children.length;
            for (int i=0; i<last; i++) {
               if(ignoreError.equalsIgnoreCase("true")) {
                   try {
                       findAndRunFiles(directoryName + "/" + children[i]);
                   }
                   catch(Exception ex) {
                       tr.log("Test hit an exception: "+ex);
                   }
               }
               else  {
                   findAndRunFiles(directoryName + "/" + children[i]);
               }
            }
            return;
        }

        tr.log("Test File "+fullName);
        // not a directory, see if it is an XPDL file
        String lcName = directoryName.toLowerCase();
        if (lcName.endsWith("xpdl")) {
            int prevPass = 0;
            int prevFail = 0;
            if (trt != null) {
                prevPass = trt.passedCount();
                prevFail = trt.failedCount();
            }
            commandLineArgs[1] = directoryName;
            tr.log("FlowPath Test: "+directoryName+"\n");
            xt.runTests(tr);
            if (trt != null) {
                trt.recordResults(directoryName, prevPass, prevFail);
                tr.log("Recorded FlowPath Test results for: "+directoryName);
            }
            return;
        }

        tr.log("Ignoring unrecognized file: "+directoryName);
    }


    /*
     * This method reads the list of directories to be excluded from
     * the file passed as a command-line argument and returns a string
     * array.
     */
    private void readExcludingDirectoryListFile(String fileName)
        throws Exception
    {
        String fullName = tr.getTestDir()+fileName;
        tr.log("Reading exclude list from "+fullName);
        File excludingDirectoryListFile = new File(fullName);
        if (!excludingDirectoryListFile.exists()) {
            checkTestDir();
            throw new Exception("Can not find the exclude file named "+fullName);
        }
        FileReader fr = new FileReader(excludingDirectoryListFile);
        BufferedReader in = new BufferedReader(fr);
        String inputLine = in.readLine();
        while (inputLine != null) {
            //the split is not really needed, but in the past there were files that
            //had a single line, with directories separated by colon characters.
            //Seems nicer to allow one line per directory/file
            //and since a path can not have a colon, this preserves compatibility
            String[] directoryList = inputLine.split(":");
            for (int i=0; i<directoryList.length; i++) {
                String oneDir = directoryList[i];
                excludeList.put(oneDir, oneDir);
            }
            inputLine = in.readLine();
        }
    }

    /**
    * Most paths in the system are relative to the "test dir" path.  If we fail to find
    * a particular file, we should first check to see if the configured test directory
    * exists and is valid.  This routine will throw an exception if the configured test
    * directory does not exist or is otherwise wrong.  Call this routine before complaining
    * about a missing file.  If this routine returns, then test directory exists, and you
    * should then throw an exception complaining about the specific file not found.
    */
    private void checkTestDir()
        throws Exception
    {
        File testDir = new File(tr.getTestDir());
        if (!testDir.exists()) {
            throw new Exception("Test configuration is somehow incorrect.  The test directory does not exist: "+tr.getTestDir());
        }
        if (!testDir.isDirectory()) {
            throw new Exception("Test configuration is somehow incorrect.  The test directory is not a directory: "+tr.getTestDir());
        }
    }

    /**
    * TestDriver is the class that knows how to run these tests.
    * So just call it with the name of this class in there.
    */
    public
    static
    void
    main(String[] args) {
        String[] newArgs = new String[2];
        newArgs[0] = "com.fujitsu.iflowqa.testframe.CollectedFlowPathTests";
        newArgs[1] = ".";
        TestDriver.main(newArgs);
    }

}

