/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.framework;

import java.io.*;
import java.util.*;

import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.sessions.*;

/**
 * <p>Purpose<b></b>: TestCollection is a collection of test suites and models. When a test collection is executed
 * all the test entities registered with it are executed one by one.
 */
public abstract class TestCollection extends junit.framework.TestSuite implements TestEntity {

    /** Store the name to allow serialization, for some reason JUnit name does not serialize. */
    private String name;

    /** Stores all the tests */
    private Vector tests;

    /** Stores the summary of the tests */
    private TestResultsSummary summary;

    /** Description of the test collection */
    private String description;
    private transient TestExecutor executor;

    /** The test collection that contains this test */
    private TestEntity container;

    /** This is used only for printing test results with proper indentation */
    private int nestedCounter;

    /** The indentation string that is added to each line of result for printing. */
    private String indentationString;

    /** Stores the last tests that were run. */
    private Vector finishedTests;

    /** A flag that indicates if the test collection is inside SRG. */
    protected boolean isSRG;

    public TestCollection() {
        initialize();
    }

    /**
     * Constructs a TestSuite from the given class with the given name.
     */
    public TestCollection(Class theClass, String name) {
        super(theClass, name);
        initialize();
    }

    /**
     * Constructs a TestSuite from the given class. Adds all the methods
     * starting with "test" as test cases to the suite.
     */
    public TestCollection(final Class theClass) {
        super(theClass);
        initialize();
    }

    public void initialize() {
        description = "";
        nestedCounter = INITIAL_VALUE;
        tests = new Vector();
        finishedTests = new Vector();
        summary = new TestResultsSummary(this);
        if ((getName() == null) || (getName().length() == 0)) {
            setName(getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1));
        } else {
            setName(getName());
        }
    }

    /**
     * Reset the JUnit name in case serialization looses it.
     */
    @Override
    public String getName() {
        if (super.getName() == null) {
            setName(this.name);
        }
        return super.getName();
    }

    /**
     * Store the test name locally to ensure it can serialize.
     */
    @Override
    public void setName(String name) {
       super.setName(name);
       this.name = name;
    }

    /**
     * Adds a test to itself
     */
    @Override
    public final void addTest(junit.framework.Test test) {
        super.addTest(test);
        if (test instanceof TestEntity) {
            ((TestEntity)test).setContainer(this);
        }
        getTests().add(test);
    }

    public abstract void addTests();

    public void addSRGTests() {
    }

    /**
     * Adds a test collection to itself
     */
    public final void addTests(Vector theTests) {
        for (Enumeration allTests = theTests.elements(); allTests.hasMoreElements();) {
            junit.framework.Test test = (junit.framework.Test)allTests.nextElement();
            addTest(test);
        }
    }

    public final void addServerTest(TestCase theTest) {
        TestCase serverTestCase;
        Class serverTestCaseClass;
        Object[] args = new Object[1];

        try {

            /** The code below is doing a roundabout version of the following (because of packaging problems):
             *
             * org.eclipse.persistence.testing.framework.ejb.ServerTestCase serverTestCase;
             * serverTestCase = new org.eclipse.persistence.testing.framework.ejb.ServerTestCase(
             *   (org.eclipse.persistence.testing.ejb20.cmp.wls.TestFramework.EJBTestCase)theTest);
             */
            serverTestCaseClass = Class.forName("org.eclipse.persistence.testing.framework.ejb.ServerTestCase");
            args[0] = theTest;
            serverTestCase = (TestCase)serverTestCaseClass.getConstructors()[0].newInstance(args);

            serverTestCase.setName(theTest.getName());
            addTest(serverTestCase);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Append test summaries of the collection of tests.
     */
    @Override
    public void appendTestResult(TestResultsSummary summary) {
        summary.appendTestCollectionResult(this);
    }

    /**
     * Computes the level for indentation.
     */
    @Override
    public void computeNestedLevel() {
        TestEntity testContainer = getContainer();

        if ((testContainer != null) && (testContainer.getNestedCounter() != INITIAL_VALUE)) {
            setNestedCounter(testContainer.getNestedCounter() + 1);
        } else {
            incrementNestedCounter();
        }
    }

    /**
     * The session is initialized to the default login from the Persistent System
     * if no explicit login is done for testing. This method must be overridden in
     * the subclasses if different login is required.
     */
    @Override
    public Session defaultLogin() {
        return (new TestSystem()).login();
    }

    /**
     * Return test collection which contains this test entity.
     */
    @Override
    public TestEntity getContainer() {
        return container;
    }

    /**
     * Return the description of the test.
     */
    public String getDescription() {
        return description;
    }

    /**
     * Return the executor.
     */
    protected TestExecutor getExecutor() {
        return executor;
    }

    public Vector getFinishedTests() {
        return finishedTests;
    }

    /**
     * Return the indentaitonString
     */
    public String getIndentationString() {
        return indentationString;
    }

    /**
     * Return the nested counter. This is used finally used to do proper indentation.
     */
    @Override
    public int getNestedCounter() {
        return nestedCounter;
    }

    /**
     * Return the summary of the test execution.
     */
    @Override
    public ResultInterface getReport() {
        return getSummary();
    }

    /**
     * Return the session.
     */
    protected org.eclipse.persistence.sessions.Session getSession() {
        return getExecutor().getSession();
    }

    /**
     * Return the session cast to DatabaseSession.
     */
    public org.eclipse.persistence.sessions.DatabaseSession getDatabaseSession() {
        return (org.eclipse.persistence.sessions.DatabaseSession)getExecutor().getSession();
    }

    /**
     * Return the session cast to AbstractSession.
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getAbstractSession() {
        return (org.eclipse.persistence.internal.sessions.AbstractSession)getExecutor().getSession();
    }

    /**
     * Return the summary of the test execution.
     */
    protected TestResultsSummary getSummary() {
        return summary;
    }

    /**
     * Return all the test entities associated with this collection.
     */
    public Vector getTests() {
        return tests;
    }

    /**
     * Counts the number of test cases that will be run by this test.
     * If the tests have not been added yet just return 1.
     */
    @Override
    public int countTestCases() {
        if (getTests().isEmpty()) {
            return 1;
        }
        return super.countTestCases();
    }

    /**
     * Returns the number of tests in this suite
     */
    @Override
    public int testCount() {
        return getTests().size();
    }

    /**
     * Returns the tests as an enumeration
     */
    @Override
    public Enumeration tests() {
        return getTests().elements();
    }

    /**
     * Returns the test at the given index
     */
    @Override
    public junit.framework.Test testAt(int index) {
        return (junit.framework.Test)getTests().elementAt(index);
    }

    @Override
    public void incrementNestedCounter() {
        setNestedCounter(getNestedCounter() + 1);
    }

    /**
     * Runs the tests and collects their result in a TestResult.
     */
    @Override
    public void run(junit.framework.TestResult result) {
        TestExecutor.setDefaultJUnitTestResult(result);
        try {
            TestExecutor executor = getExecutor();
            if (executor == null) {
                executor = TestExecutor.getDefaultExecutor();
            }
            execute(executor);
        } catch (Throwable exception) {
            if (exception instanceof TestWarningException) {
                    System.out.println("WARNING: " + exception);
            } else {
                result.addError(this, exception);
            }
        }
    }

    /**
     * Add foot note the the result for printing.
     */
    abstract protected void logFootNote(Writer log);

    /**
     * Add head note the the result for printing.
     * This method is added to migrate tests to Ora*Tst
     */
    abstract protected void logRegressionHeadNote(Writer log);

    /**
     * Add head note the the result for printing.
     */
    abstract protected void logHeadNote(Writer log);

    /**
     * Logs the result summary of the suite on the print stream.
     * This method is added to migrate tests to Ora*Tst
     */
    @Override
    public void logRegressionResult(Writer log) {
        logResult(log, false, true);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    @Override
    public void logResult(Writer log) {
        logResult(log, false, false);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    @Override
    public void logResult(Writer log, boolean logOnlyErrors) {
        logResult(log, logOnlyErrors, false);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    public void logResult(Writer log, boolean logOnlyErrors, boolean regression) {
        computeResultSummary();
        setIndentationString(Helper.getTabs(getNestedCounter()));

        if (regression) {
            logRegressionHeadNote(log);
        } else {
            logHeadNote(log);
        }

        for (Enumeration tests = getFinishedTests().elements(); tests.hasMoreElements();) {
            junit.framework.Test test = ((junit.framework.Test)tests.nextElement());
            if (test instanceof TestEntity) {
                TestEntity testEntity = (TestEntity)test;
                if (regression) {
                    if (!(testEntity instanceof TestCase) || !(testEntity.getReport().hasPassed() || ((TestResult)testEntity.getReport()).hasWarning())) {
                        testEntity.logRegressionResult(log);
                    }
                } else {
                    if ((!(testEntity instanceof TestCase)) || testEntity.getReport().shouldLogResult()) {
                        if (!logOnlyErrors || !(testEntity instanceof TestCollection) || !testEntity.getReport().hasPassed()) {
                            testEntity.logResult(log, logOnlyErrors);
                        }
                    }
                }
            } else {
                TestExecutor.logJUnitResult(test, log, Helper.getTabs(getNestedCounter() + 1));
            }
        }

        logFootNote(log);
        if (regression) {
            getSummary().logRegressionResult(log);
        } else {
            getSummary().logResult(log);
        }
    }

    /**
     * Compute the reuslt summary.
     */
    public void computeResultSummary() {
        getSummary().resetTotals();
        for (Enumeration tests = getFinishedTests().elements(); tests.hasMoreElements();) {
            junit.framework.Test test = ((junit.framework.Test)tests.nextElement());
            if (test instanceof TestCase) {
                TestCase testEntity = (TestCase)test;
                testEntity.appendTestResult(getSummary());
            } else if (test instanceof TestCollection) {
                TestCollection testEntity = (TestCollection)test;
                testEntity.computeResultSummary();
                testEntity.appendTestResult(getSummary());
            } else {
                junit.framework.TestResult result = (junit.framework.TestResult) TestExecutor.getJUnitTestResults().get(test);
                getSummary().appendTestResult(result);
            }
        }
    }

    /**
     * Remove the test colleciton.
     */
    protected void removeTest(TestEntity test) {
        getTests().removeElement(test);
    }

    @Override
    public boolean requiresDatabase() {
        return true;
    }

    @Override
    public abstract void resetEntity();

    /**
     * Reinitialize the nested counter value.
     */
    @Override
    public void resetNestedCounter() {
        setNestedCounter(INITIAL_VALUE);
        for (Enumeration tests = getTests().elements(); tests.hasMoreElements();) {
            Object test = tests.nextElement();
            if (test instanceof TestEntity) {
                ((TestEntity)test).resetNestedCounter();
            }
        }
    }

    /**
     * Set the test collection which contains this test
     */
    @Override
    public void setContainer(TestEntity testEntity) {
        container = testEntity;
    }

    /**
     * Set the description of the test.
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Set the executor.
     */
    public void setExecutor(TestExecutor anExecutor) {
        executor = anExecutor;
    }

    public void setFinishedTests(Vector finishedTests) {
        this.finishedTests = finishedTests;
    }

    /**
     * Set the indentaitonString
     */
    public void setIndentationString(String indentationString) {
        this.indentationString = indentationString;
    }

    /**
     * Set the nested counter value.
     */
    @Override
    public void setNestedCounter(int level) {
        this.nestedCounter = level;
    }

    /**
     * Set the summary of the test collection.
     */
    protected void setSummary(TestResultsSummary theSummary) {
        summary = theSummary;
        theSummary.setTestCollection(this);
    }

    /**
     * Set the test result.
     */
    @Override
    public void setReport(ResultInterface summary) {
        setSummary((TestResultsSummary)summary);
    }

    protected final void setTests(Vector theTests) {
        tests = theTests;
    }

    public abstract void setupEntity() throws Throwable;

    /**
     * Print the test as its name.
     */
    public String toString() {
        return getName();
    }
}
