/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/


package base;


import basicrunner.BasicIfcTest;
import basicrunner.BasicTestCase;

import com.sun.star.lang.XMultiServiceFactory;

import helper.APIDescGetter;
import helper.AppProvider;
import helper.OfficeProvider;
import helper.OfficeWatcher;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;

import java.util.Vector;

import lib.TestCase;
import lib.TestEnvironment;
import lib.TestParameters;

import share.DescEntry;
import share.DescGetter;
import share.LogWriter;

import stats.OutProducerFactory;
import stats.Summarizer;

import util.DynamicClassLoader;

/**
 * The testbase for executing basic tests.
 *  @see lib.TestBase
 */
public class basic_fat implements TestBase
{

    public static boolean debug = false;

    /**
     *  Execute a test.
     *  @param param The test parameters.
     * @return True, if the test was executed.
     */
    public boolean executeTest(TestParameters param)
    {
        DescGetter dg = new APIDescGetter();
        String job = (String) param.get("TestJob");
        OfficeProvider office = null;
        debug = param.getBool("DebugIsActive");


        //get Job-Descriptions
        System.out.print("Getting Descriptions for Job: " + job + " from ");

        DescEntry[] entries = dg.getDescriptionFor(job,
                (String) param.get(
                "DescriptionPath"),
                debug);

        if (entries == null)
        {
            System.out.println("Couldn't get Description for Job");

            return false;
        }

        String ExclusionFile = (String) param.get("ExclusionList");
        Vector exclusions = null;

        if (ExclusionFile != null)
        {
            exclusions = getExclusionList(ExclusionFile, debug);
        }

        String conStr = (String) param.get("ConnectionString");
        System.out.println("");
        System.out.print("> Connecting the Office ");
        System.out.println("With " + conStr);

        for (int l = 0; l < entries.length; l++)
        {
            if (entries[l].hasErrorMsg)
            {
                System.out.println(entries[l].ErrorMsg);

                continue;
            }

            office = new OfficeProvider();

            XMultiServiceFactory msf = (XMultiServiceFactory) office.getManager(
                    param);

            if (msf == null)
            {
                return false;
            }

            param.put("ServiceFactory", msf);

            DescEntry entry = entries[l];

            //get some helper classes
            Summarizer sumIt = new Summarizer();
            DynamicClassLoader dcl = new DynamicClassLoader();

            TestCase tCase = null;

            tCase = (TestCase) new BasicTestCase(entry);

            if (tCase == null)
            {
                sumIt.summarizeDown(entry, entry.ErrorMsg);

                LogWriter sumObj = OutProducerFactory.createOutProducer(param);
                sumObj.initialize(entry, true);
                sumObj.summary(entry);

                continue;
            }

            System.out.println("Creating: " + tCase.getObjectName());

            LogWriter log = (LogWriter) dcl.getInstance(
                    (String) param.get("LogWriter"));
            log.initialize(entry, true);
            entry.UserDefinedParams = param;
            tCase.setLogWriter((PrintWriter) log);

            try
            {
                tCase.initializeTestCase(param);
            }
            catch (RuntimeException e)
            {
                helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                        "AppProvider");

                if (ph != null)
                {
                    OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");

                    if ((ow != null) && ow.isAlive())
                    {
                        ow.finish = true;
                    }

                    ph.kill();
                    shortWait(5000);
                }

                continue;
            }

            TestEnvironment tEnv = tCase.getTestEnvironment(param);

            if (tEnv == null)
            {
                sumIt.summarizeDown(entry, "Unable to create testcase");

                LogWriter sumObj = OutProducerFactory.createOutProducer(param);
                sumObj.initialize(entry, true);
                sumObj.summary(entry);

                helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                        "AppProvider");

                if (ph != null)
                {
                    OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");

                    if ((ow != null) && ow.isAlive())
                    {
                        ow.finish = true;
                    }

                    ph.kill();
                    shortWait(5000);
                }

                continue;
            }

            System.out.println("created " + tCase.getObjectName());

            for (int j = 0; j < entry.SubEntryCount; j++)
            {
                if (!entry.SubEntries[j].isToTest)
                {
                    Summarizer.summarizeDown(entry.SubEntries[j],
                            "not part of the job");

                    continue;
                }

                if ((exclusions != null) &&
                        (exclusions.contains(entry.SubEntries[j].longName)))
                {
                    Summarizer.summarizeDown(entry.SubEntries[j],
                            "known issue");

                    continue;
                }

                System.out.println("running: " +
                        entry.SubEntries[j].entryName);

                LogWriter ifclog = (LogWriter) dcl.getInstance(
                        (String) param.get("LogWriter"));
                ifclog.initialize(entry.SubEntries[j], true);
                entry.SubEntries[j].UserDefinedParams = param;
                entry.SubEntries[j].Logger = ifclog;

                if ((tEnv == null) || tEnv.isDisposed())
                {
                    helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                            "AppProvider");

                    if (ph != null)
                    {
                        office.closeExistingOffice(param, true);
                        shortWait(5000);
                    }

                    tEnv = getEnv(entry, param);
                }

                BasicIfcTest ifc = null;
                lib.TestResult res = null;
                ifc = new BasicIfcTest(entry.SubEntries[j].longName);
                res = ifc.run(entry.SubEntries[j], tEnv, param);

                sumIt.summarizeUp(entry.SubEntries[j]);

                LogWriter sumIfc = OutProducerFactory.createOutProducer(param);

                sumIfc.initialize(entry.SubEntries[j], true);
                sumIfc.summary(entry.SubEntries[j]);
            }

            try
            {
                tCase.cleanupTestCase(param);
            }
            catch (Exception e)
            {
                log.println("TestCase already gone");

                helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                        "AppProvider");

                if (ph != null)
                {
                    office.closeExistingOffice(param, true);
                    shortWait(5000);
                }
            }

            sumIt.summarizeUp(entry);

            LogWriter sumObj = OutProducerFactory.createOutProducer(param);
            sumObj.initialize(entry, true);
            sumObj.summary(entry);
        }

        if (entries.length > 1)
        {
            System.out.println();

            int counter = 0;
            System.out.println(
                    "Failures that appeared during scenario execution:");

            for (int i = 0; i < entries.length; i++)
            {
                if (!entries[i].State.endsWith("OK"))
                {
                    System.out.println("\t " + entries[i].longName);
                    counter++;
                }
            }

            System.out.println(counter + " of " + entries.length +
                    " tests failed");
        }

        helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                "AppProvider");

        if (ph != null)
        {
            office.closeExistingOffice(param, true);
        }

        return true;
    }

    protected TestEnvironment getEnv(DescEntry entry, TestParameters param)
    {
        DynamicClassLoader dcl = new DynamicClassLoader();
        String officeProviderName = (String) param.get("OfficeProvider");
        AppProvider office = (AppProvider) dcl.getInstance(officeProviderName);

        if (office == null)
        {
            System.out.println("ERROR: Wrong parameter 'OfficeProvider', " +
                    " it cannot be instantiated.");
            System.exit(-1);
        }

        XMultiServiceFactory msf = (XMultiServiceFactory) office.getManager(
                param);

        if (msf == null)
        {
            return null;
        }

        param.put("ServiceFactory", msf);

        TestCase tCase = (TestCase) new BasicTestCase(entry);

        System.out.println("Creating: " + tCase.getObjectName());

        LogWriter log = (LogWriter) dcl.getInstance(
                (String) param.get("LogWriter"));
        log.initialize(entry, true);
        entry.UserDefinedParams = param;
        tCase.setLogWriter((PrintWriter) log);

        TestEnvironment tEnv = null;

        try
        {
            tCase.initializeTestCase(param);
            tEnv = tCase.getTestEnvironment(param);
        }
        catch (java.lang.RuntimeException e)
        {
            System.out.println(e.getMessage());

            helper.ProcessHandler ph = (helper.ProcessHandler) param.get(
                    "AppProvider");

            if (ph != null)
            {
                office.closeExistingOffice(param, true);
                shortWait(5000);
            }

            entry.ErrorMsg = e.getMessage();
            entry.hasErrorMsg = true;
        }

        return tEnv;
    }

    protected void shortWait(int millis)
    {
        try
        {
            Thread.sleep(millis);
        }
        catch (java.lang.InterruptedException ie)
        {
        }
    }

    protected Vector getExclusionList(String url, boolean debug)
    {
        Vector entryList = new Vector();
        String line = "#";
        BufferedReader exclusion = null;

        try
        {
            exclusion = new BufferedReader(new FileReader(url));
        }
        catch (java.io.FileNotFoundException fnfe)
        {
            if (debug)
            {
                System.out.println("Couldn't find file " + url);
            }

            return entryList;
        }

        while (line != null)
        {
            try
            {
                if (!line.startsWith("#"))
                {
                    entryList.add(line);
                }

                line = exclusion.readLine();
            }
            catch (java.io.IOException ioe)
            {
                if (debug)
                {
                    System.out.println(
                            "Exception while reading exclusion list");
                }

                return entryList;
            }
        }

        try
        {
            exclusion.close();
        }
        catch (java.io.IOException ioe)
        {
            if (debug)
            {
                System.out.println("Couldn't close file " + url);
            }

            return entryList;
        }

        return entryList;
    }
}
