/*
 * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.xmlutil;

import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Document;
import org.jdom.input.JDOMFactory;
import org.apache.log4j.Logger;

import java.util.List;
import java.util.Iterator;
import java.util.LinkedList;

import com.arsdigita.util.StringUtils;

public class TestDefinition extends Element {
    private static Logger s_log = Logger.getLogger(TestDefinition.class);

    public static final String NAME = "test_def";
    public TestDefinition() {
        this( NAME, Namespaces.TEST );
    }
    public TestDefinition(String name) {
        super(NAME, Namespaces.TEST);
    }
    public TestDefinition(String name, Namespace ns) {
        super(NAME, Namespaces.TEST);
    }
    public TestDefinition(String name, String uri) {
        super(NAME, Namespaces.TEST);
    }
    public TestDefinition(String name, String prefix, String uri) {
        super(NAME, Namespaces.TEST);
    }

   public void runTest() throws Exception {
       executeDependentTests();
       List testActions = getChildren("actions", Namespaces.TEST);
       s_log.warn("TestDef has " + testActions.size() + " Elements.");
       for (Iterator iterator = testActions.iterator(); iterator.hasNext();) {
           Element actionsElement = (Element) iterator.next();
           executeTestActions(actionsElement);

       }
   }

    private void executeDependentTests() throws Exception {
        Element externalDefs = getChild("dependent_tests", Namespaces.TEST);
        if (null != externalDefs) {
            TestDocument parentDoc = (TestDocument) getDocument();
            DocImporter importer = new DocImporter(false);
            importer.setJDOMFactory(parentDoc.getFactory());

            List tests = externalDefs.getChildren();
            for (Iterator iterator = tests.iterator(); iterator.hasNext();) {
                Element externalTest = (Element) iterator.next();
                String testFile = externalTest.getAttributeValue("file");
                executeDependentTest(testFile, importer);
            }
        }
    }

    private void executeDependentTest(String testFile, DocImporter importer) throws Exception {
        Document doc = importer.getDocumentAsResource(testFile);
        TestSet set = (TestSet) doc.getRootElement();
        set.runTests();
     }

    private void executeTestActions(Element actionsElement) throws Exception {
        List children = actionsElement.getChildren();

        for (Iterator actions = children.iterator(); actions.hasNext();) {
            TestAction action  = (TestAction) actions.next();
            Exception error = null;
            try {
                action.execute();
                if ( action.shouldFail() ) {
                    error = new XMLException("Test acton didn't fail!", action);
                }
            } catch (Exception e) {
                if ( action.shouldFail() == false ) {
                    error = new XMLException("Unexpected failure of test action!", e, action);
                }
                // Log the exception just in case it is invalid. The way the system is set up,
                // if an unexpected error occurs during a test that should fail, it will be
                // considered to 'pass'. This may not be correct.
                s_log.info("shouldFail with exception", e);
            }

            if ( null != error ) {
                throw error;
            }
        }
    }
}
