/**************************************************************
 * 
 * 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 lib;

import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;

import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XInterface;

import share.DescEntry;
import lib.TestParameters;
import stats.Summarizer;

/**
 * The class supports method based interface tests development.
 *
 * <p>There are some points that should be fulfilled in a subclass to work
 * correctly in the multi-method framework:
 *
 *   1. each subclass schould define a public field named oObj of type tested
 *   by the subclass, e.g. 'public XText oObj;'. That field will be initialized
 *   by the MultiMethodTest code with the instance of the interface to test.
 *   In a case of service testing the field type should be XPropertySet.
 *
 *   2. for the test of each method of the tested interface(or a property in the
 *   case of service testing) should be method with the following signature
 *   provided: 'public void _<method name>()', e.g. 'public void _getText()'.
 *   The methods will be called by MultiMethodText code using reflection API
 *   for each method in the interface description.
 *
 *   3. to set status for a call 'tRes.tested(String method,
 *   boolean result)' should be used. For example 'tRes.tested("getText()",
 *   true)'. Also 'tRes.assert(String assertion, boolean result)' call can
 *   be used. Note, that one can call the methods not neccesarily from the
 *   test for the tested method, but from other method tests too (in the
 *   MultiMethodTest subclass). See also TestResult and MultiMethodTest.tRes
 *   documentation.
 *
 *   4. the before() and after() methods can be overriden to perform some
 *   actions, accordingly, before and after calling the test methods.
 *
 *   5. besides tRes, there are some fields initialized in the MultiMethodTest,
 *   that can be used for implementing tests:
 *
 *     - tEnv contains the environment tested
 *     - tParam contains parameters of the test
 *     - log a writer to log information about the test
 *
 * @see TestResult
 */
public class MultiMethodTest
{

    /**
     * Contains the TestEnvironment being tested, to allow for tests to access
     * it.
     */
    protected TestEnvironment tEnv;
    /**
     * Contains the TestParameters for the tests, to allow for tests to access
     * it.
     */
    protected TestParameters tParam;
    /**
     * Contains the Description for the test
     * it.
     */
    protected DescEntry entry;
    /**
     * Contains a writer to log an information about the interface testing, to
     * allows for tests to access it.
     */
    protected PrintWriter log;
    /**
     * Contains the TestResult instance for the interface test to collect
     * information about methods test.
     */
    protected TestResult tRes;
    /**
     * Contains names of the methods have been alreadycalled
     */
    private Vector methCalled = new Vector(10);

    /**
     * Disposes the test environment, which was corrupted by the test.
     *
     * @param tEnv the environment to dispose
     */
    public void disposeEnvironment(TestEnvironment tEnv)
    {
        disposeEnvironment();
    }

    /**
     * Disposes the current test environment, which was corrupted by the test.
     *
     * @see #disposeEnvironment(TestEnvironment)
     */
    public void disposeEnvironment()
    {
        tEnv.dispose();
        TestCase tCase = tEnv.getTestCase();
        tCase.disposeTestEnvironment(tEnv, tParam);
    }

    /**
     * Runs the interface test: its method tests. First, it initializes some
     * of MultiMethodTest fields, like tRes, log, tEnv, etc. Then, it queries
     * the tested interface and initializes 'oObj' field (defined in a
     * subclass). Before calling method tests, before() method calles to allow
     * initialization of s stuff before testing. Then, the method tests are
     * called. After them, after() method is called, to allow cleaning up the
     * stuff initialized in before() and test methods.
     *
     * @param entry the interface test state
     * @param tEnv the environment to test
     * @param tParam the parameters of the test
     *
     * @see #before
     * @see #after
     */
    public TestResult run(DescEntry entry, TestEnvironment tEnv, TestParameters tParam)
    {

        log = (PrintWriter) entry.Logger;

        this.tEnv = tEnv;
        this.tParam = tParam;
        // this.log = log;
        this.entry = entry;
        this.tRes = new TestResult();
        Class testedClass;

        // Some fake code for a self test.
        // For normal test we must not be a "ifc.qadevooo._SelfTest"
        if (! entry.entryName.equals("ifc.qadevooo._SelfTest"))
        {
            String ifcName = getInterfaceName();
            // System.out.println("checking : " + ifcName);
            System.out.print("checking: [" + entry.longName + "]");
            
            // defining a name of the class corresponding to the tested interface
            // or service
            String testedClassName;

            testedClassName = getTestedClassName();

            if (entry.EntryType.equals("service"))
            {
                testedClassName = "com.sun.star.beans.XPropertySet";
            }

            try
            {
                testedClass = Class.forName(testedClassName);
            }
            catch (ClassNotFoundException cnfE)
            {
                System.out.println();
                cnfE.printStackTrace(log);
                log.println("could not find a class : " + getTestedClassName());
                return null;
            }
            System.out.println(" is iface: [" + testedClassName + "] testcode: [" + entry.entryName + "]");

            // quering the tested interface from the tested object
            XInterface tCase = tEnv.getTestObject();
            Object oObj = UnoRuntime.queryInterface(testedClass, tEnv.getTestObject());

            if (oObj == null)
            {
                if (entry.isOptional)
                {
                    Summarizer.summarizeDown(entry, "Not supported but optional.OK");
                }
                else
                {
                    Summarizer.summarizeDown(entry, "queryInterface returned null.FAILED");
                    entry.ErrorMsg = "queryInterface returned null";
                    entry.hasErrorMsg = true;
                }

                return null;
            }

            //setting the field oObj
            setField("oObj", oObj);
        }

        // to perform some stuff before all method tests
        try
        {
            before();
        }
        catch (Exception e)
        {
            setSubStates(e.toString());
            return tRes;
        }

        // executing methods tests
        for (int i = 0; i < entry.SubEntryCount; i++)
        {
            DescEntry aSubEntry = entry.SubEntries[i];
            try
            {
                final String sEntryName = aSubEntry.entryName;
                executeMethod(sEntryName);
            }
            catch (Exception e)
            {
                log.println("Exception while checking: " + aSubEntry.entryName + " : " + e.getMessage());
            }
        }

        // to perform some stuff after all method tests
        try
        {
            after();
        }
        catch (Exception e)
        {
        }

        return tRes;
    }

    /**
     * Is called before calling method tests, but after initialization.
     * Subclasses may override to perform actions before method tests.
     */
    protected void before()
    {
    }

    /**
     * Is called after calling method tests. Subclasses may override
     * to perform actions after method tests.
     */
    protected void after()
    {
    }

    /**
     * @return the name of the interface or the service tested.
     */
    protected String getTestedClassName()
    {
        String clsName = this.getClass().getName();

        int firstDot = clsName.indexOf(".");
        int lastDot = clsName.lastIndexOf(".");

        String append = "com.sun.star.";

        if (entry.longName.indexOf("::drafts::com::") > -1)
        {
            append = "drafts.com.sun.star.";
        }

        return append + clsName.substring(firstDot + 1, lastDot + 1) + clsName.substring(lastDot + 2);
    }

    /**
     * Sets a method status.
     *
     * @param methName the method name to set status
     * @param methStatus the status to set to the method
     */
    protected void setStatus(String methName, Status methStatus)
    {
        tRes.tested(methName, methStatus);
    }

    /**
     * sets the substates
     */
    protected void setSubStates(String msg)
    {
        for (int k = 0; k < entry.SubEntryCount; k++)
        {
            entry.SubEntries[k].hasErrorMsg = true;
            entry.SubEntries[k].ErrorMsg = msg;
            if (entry.SubEntries[k].State.equals("UNKNOWN"))
            {
                entry.SubEntries[k].State = msg;
            }
        }

    }

    /**
     * Checks if the <code>method</code> is optional in the service.
     */
    protected boolean isOptional(String _method)
    {
        for (int k = 0; k < entry.SubEntryCount; k++)
        {
            final String sName = entry.SubEntries[k].entryName;
            if (sName.equals(_method))
            {
                final boolean bIsOptional = entry.SubEntries[k].isOptional;
                return bIsOptional;
            }
        }
        return false;
    }

    /**
     * Checks if the <code>method</code> test has been already called.
     */
    protected boolean isCalled(String method)
    {
        return methCalled.contains(method);
    }

    /**
     * Calling of the method indicates that the <code>method</code> test should
     * be called. The method checks this and if it is not called, calls it.
     * If the method is failed or skipped, it throws StatusException.
     */
    protected void requiredMethod(String method)
    {
        log.println("starting required method: " + method);
        executeMethod(method);
        Status mtStatus = tRes.getStatusFor(method);

        if (mtStatus != null && (!mtStatus.isPassed() || mtStatus.isFailed()))
        {
            log.println("! Required method " + method + " failed");
            throw new StatusException(mtStatus);
        }
    }

    /**
     * Checks if the <code>method</code> was called, and if not, call it.
     * On contrary to requiredMethod(), he method doesn't check its status.
     */
    protected void executeMethod(String method)
    {
        if (!isCalled(method))
        {
            log.println("Execute: " + method);
            callMethod(method);
            log.println(method + ": " + tRes.getStatusFor(method));
            log.println();
        }
    }

    /**
     * Just calls the <code>method</code> test.
     */
    protected void callMethod(String method)
    {
        methCalled.add(method);
        invokeTestMethod(getMethodFor(method), method);
    }

    /**
     * Invokes a test method of the subclass using reflection API. Handles
     * the method results and sets its status.
     *
     * @param meth the subclass' method to invoke
     * @param methName the name of the method
     */
    protected void invokeTestMethod(Method meth, String methName)
    {
        if (meth == null)
        {
            setStatus(methName, Status.skipped(false));
        }
        else
        {
            Status stat;

            try
            {
                meth.invoke(this, new Object[0]);
                return;
            }
            catch (InvocationTargetException itE)
            {
                Throwable t = itE.getTargetException();

                if (t instanceof StatusException)
                {
                    stat = ((StatusException) t).getStatus();
                }
                else
                {
                    t.printStackTrace(log);
                    stat = Status.exception(t);
                }
            }
            catch (IllegalAccessException iaE)
            {
                iaE.printStackTrace(log);
                stat = Status.exception(iaE);
            }
            catch (IllegalArgumentException iaE)
            {
                iaE.printStackTrace(log);
                stat = Status.exception(iaE);
            }
            catch (ClassCastException ccE)
            {
                ccE.printStackTrace(log);
                stat = Status.exception(ccE);
            }

            setStatus(methName, stat);
        }
    }

    /**
     * Finds a testing method for the <code>method</code> of the interface.
     *
     * @return the testing method, if found, <tt>null</tt> otherwise
     */
    protected Method getMethodFor(String method)
    {
        String mName = "_" + method;

        if (mName.endsWith("()"))
        {
            mName = mName.substring(0, mName.length() - 2);
        }

        final Class[] paramTypes = new Class[0];

        try
        {
            return this.getClass().getDeclaredMethod(mName, paramTypes);
        }
        catch (NoSuchMethodException nsmE)
        {
            return null;
        }
    }

    /**
     * @return the name of the interface tested
     */
    public String getInterfaceName()
    {
        String clName = this.getClass().getName();
        return clName.substring(clName.lastIndexOf('.') + 1);
    }

    /**
     * Initializes <code>fieldName</code> of the subclass with
     * <code>value</code>.
     *
     * @return Status describing the result of the operation.
     */
    protected Status setField(String fieldName, Object value)
    {
        Field objField;

        try
        {
            objField = this.getClass().getField(fieldName);
        }
        catch (NoSuchFieldException nsfE)
        {
            return Status.exception(nsfE);
        }

        try
        {
            objField.set(this, value);
            return Status.passed(true);
        }
        catch (IllegalArgumentException iaE)
        {
            return Status.exception(iaE);
        }
        catch (IllegalAccessException iaE)
        {
            return Status.exception(iaE);
        }
    }
}
