/*
 * 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.
 */
// Base header file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>



#include <iomanip>



#include <xalanc/Include/XalanMemoryManagement.hpp>



#include <xalanc/XalanTransformer/XalanParsedSource.hpp>



#include <xalanc/PlatformSupport/DOMStringHelper.hpp>



#include <xalanc/XalanDOM/XalanDocument.hpp>
#include <xalanc/XalanDOM/XalanNode.hpp>
#include <xalanc/XalanDOM/XalanNamedNodeMap.hpp>
#include <xalanc/XalanDOM/XalanDOMString.hpp>



#include <xalanc/Harness/XalanFileUtility.hpp>



#include "Parameters.hpp"
#include "Utils.hpp"



using xalanc::XalanTransformer;
using xalanc::XalanParsedSource;
using xalanc::XalanDocument;
using xalanc::XalanNode;
using xalanc::XalanNamedNodeMap;
using xalanc::XalanDOMString;
using xalanc::WideStringToLong;
using xalanc::compareIgnoreCaseASCII;
using xalanc::XalanMemMgrs;
using xalanc::MemoryManager;
using xalanc::XalanFileUtility;
using xalanc::XSLTInputSource;





using std::endl;



/**
 * Processes parameters for the test harness
 */
Parameters::Parameters(
        const XalanDOMString&   runFileName,
        const XalanDOMString&   testDirectory,
        const XalanDOMString&   resultDirectory,
        const XalanDOMString&   baselineDirectory,
        const XalanDOMString&   reportDirectory,
        XalanFileUtility&       fileUtility,
        Logger&                 logger) :
    m_name("default"),
    m_description(""),
    m_resultDirectory(resultDirectory),
    m_resultFile("results"),
    m_threshold("5"),
    m_baselineDirectory(baselineDirectory),
    m_baselineFile(""),
    m_defaultTestCase(),
    m_testDirectory(testDirectory),
    m_goldDirectory(""),
    m_reportDirectory(reportDirectory),
    m_transformer(),
    m_uniqId(),
    m_initialized(false)
{
    fileUtility.generateUniqRunid(m_uniqId);

    if (parseConfigurationFile(runFileName, logger))
    {
        if (m_testDirectory.empty())
        {
            logger.error() << "No test directory specified on command line or in configuration file" << endl;
        }
        else
        {
            // configure directories
            // result directory
            if (m_resultDirectory.empty())
            {
                m_resultDirectory = getWorkingDirectory();
            }
            m_resultDirectory += getPathSep();

            // gold directory
            if (m_goldDirectory.empty())
            {
                m_goldDirectory = m_testDirectory;
                m_goldDirectory += XalanDOMString("-gold");
            }
            
            // test directory
            m_testDirectory += getPathSep();

            if (readTestCases(fileUtility, logger))
            {
                m_initialized = true;
            }

            // baseline directory
            if (m_baselineDirectory.empty())
            {
                m_baselineDirectory = m_resultDirectory;
            }
            else
            {
                m_baselineDirectory += getPathSep();
            }

            if (m_baselineFile.empty())
            {
                m_baselineFile = m_resultFile;
                m_baselineFile += XalanDOMString("_latest.xml");
            }

            // report directory
            if (m_reportDirectory.empty())
            {
                m_reportDirectory = getWorkingDirectory();
            }
            m_reportDirectory += getPathSep();
        }
    }
}



const TestCasesType& 
Parameters::getTestCases()
{
    return m_testCases;
}



bool
Parameters::parseConfigurationFile(
        const XalanDOMString&   runFileName,
        Logger&                 logger)
{
    // parse the configuration file and get default settings

    const XalanParsedSource* theParsedSource;

    XSLTInputSource confFile(runFileName, m_transformer.getMemoryManager());

    if (m_transformer.parseSource(confFile, theParsedSource) < 0)
    {
        logger.error() << "Failed to parse: " 
                << runFileName.c_str() 
                << ", error: " 
                << m_transformer.getLastError() 
                << endl;

        return false;
    }

    XalanDocument* document = theParsedSource->getDocument();

    XalanNode* runNode = document->getFirstChild();

    while (runNode->getNodeType() != XalanNode::ELEMENT_NODE)
    {
        runNode = runNode->getNextSibling();
        if (0 == runNode)
        {
            logger.error() << "Failed to parse: " 
                << runFileName.c_str() 
                << ", error: no <testconfig> found"
                << endl;

            return false;
        }
    }

    if(!(runNode->getNodeName() == XalanDOMString("testconfig")))
    {
        logger.error() << "Invalid configuration file: "
                << runFileName.c_str()
                << ", error: Missing <testconfig> tag" 
                << endl;

        return false;
    }

    const XalanNamedNodeMap* attributes = runNode->getAttributes();

    if (attributes != 0)
    {
        XalanNode* nameAttribute = attributes->getNamedItem(XalanDOMString("name"));

        if (nameAttribute != 0 &&
            !nameAttribute->getNodeValue().empty())
        {
            m_name = nameAttribute->getNodeValue();
        }
        else
        {
            logger.error() << "Invalid configuration file: "
                << runFileName.c_str()
                << ", error: Missing name attribute" 
                << endl;

            return false;
        }
    }

    XalanNode* currentNode = runNode->getFirstChild();

    while(currentNode != 0)
    {
        if (currentNode->getNodeType() != XalanNode::ELEMENT_NODE)
        {
            currentNode = currentNode->getNextSibling();
            continue;
        }

        // description element 
        if (currentNode->getNodeName() == XalanDOMString("description") &&
            currentNode->getFirstChild() != 0 &&
            currentNode->getFirstChild()->getNodeType() == XalanNode::TEXT_NODE)
        {
            m_description = currentNode->getFirstChild()->getNodeValue();
        }
        // results element
        else if (currentNode->getNodeName() == XalanDOMString("results"))
        {
            // file-path
            const XalanNamedNodeMap* resultAttributes = currentNode->getAttributes();
            XalanNode * attributeNode = resultAttributes->getNamedItem(XalanDOMString("file-path"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE)
            {
                if (!m_resultDirectory.empty())
                {
                    m_resultDirectory += getPathSep();
                }
                m_resultDirectory += attributeNode->getNodeValue();
            }

            // result report file name
            XalanNode * resultsNode = currentNode->getFirstChild();
            if (resultsNode != 0 
                && resultsNode->getNodeType() == XalanNode::TEXT_NODE
                && !resultsNode->getNodeValue().empty())
            {
                m_resultFile = resultsNode->getNodeValue();
            }
        }
        // baseline element
        else if (currentNode->getNodeName() == XalanDOMString("baseline"))
        {
            const XalanNamedNodeMap* attributeParams = currentNode->getAttributes();
            XalanNode* attributeNode;
            // threshold
            attributeNode = attributeParams->getNamedItem(XalanDOMString("threshold"));
            if (attributeNode != 0
                && !attributeNode->getNodeValue().empty())
            {
                m_threshold = attributeNode->getNodeValue().c_str();
            }
            // file-path
            attributeNode = attributeParams->getNamedItem(XalanDOMString("file-path"));
            if (attributeNode != 0)
            {
                if (!m_baselineDirectory.empty())
                {
                    m_baselineDirectory += getPathSep();
                }
                m_baselineDirectory += attributeNode->getNodeValue();
            }
            // baseline file
            XalanNode * baselineNode = currentNode->getFirstChild();
            if (baselineNode != 0
                && baselineNode->getNodeType() == XalanNode::TEXT_NODE
                && !baselineNode->getNodeValue().empty())
            {
                m_baselineFile += baselineNode->getNodeValue();
            }
        }
        // default parameters
        else if (currentNode->getNodeName() == XalanDOMString("default-parameter-set"))
        {
            const XalanNamedNodeMap* attributeParams = currentNode->getAttributes();
            XalanNode* attributeNode;
            attributeNode = attributeParams->getNamedItem(XalanDOMString("input-mode"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE &&
                !attributeNode->getNodeValue().empty())
            {
                m_defaultTestCase.inputMode = attributeNode->getNodeValue(); 
            }
            // number of iterations
            attributeNode = attributeParams->getNamedItem(XalanDOMString("num-iterations"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE &&
                WideStringToLong(attributeNode->getNodeValue().c_str()) > 0)
            {
                m_defaultTestCase.numIterations = WideStringToLong(attributeNode->getNodeValue().c_str()); 
            }
            // minimum time to execute
            attributeNode = attributeParams->getNamedItem(XalanDOMString("min-time-to-execute"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE &&
                WideStringToLong(attributeNode->getNodeValue().c_str()) > 0)
            {
                m_defaultTestCase.minTimeToExecute = WideStringToLong(attributeNode->getNodeValue().c_str());
            }
            // verify the result
            attributeNode = attributeParams->getNamedItem(XalanDOMString("verify-result"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE &&
                compareIgnoreCaseASCII(attributeNode->getNodeValue().c_str(),XalanDOMString("yes").c_str()) == 0)
            {
                m_defaultTestCase.verifyResult = true;
            }
            // get processor specific parameters
            XalanNode * options = currentNode->getFirstChild();
            while (options != 0)
            {
                if (options->getNodeType() != XalanNode::ELEMENT_NODE)
                {
                    options = options->getNextSibling();
                    continue;
                }

                const XalanDOMString* processorName = 0;

                const XalanNamedNodeMap* optionAttributes = options->getAttributes();
                XalanNode* processorOption = optionAttributes->getNamedItem(XalanDOMString("processor"));
                if (processorOption != 0 &&
                    processorOption->getNodeType() == XalanNode::ATTRIBUTE_NODE)
                {
                    processorName = &(processorOption->getNodeValue());
                }

                if (processorName != 0 && processorName->empty() == true)
                {
                    options = options->getNextSibling();
                    continue;
                }

                if (options->getNodeName() == XalanDOMString("init-options"))
                {
                    m_defaultTestCase.processorOptions[*processorName].initOptions = options->getFirstChild();
                }
                else if (options->getNodeName() == XalanDOMString("compile-options"))
                {
                    m_defaultTestCase.processorOptions[*processorName].compileOptions = options->getFirstChild();
                }
                else if (options->getNodeName() == XalanDOMString("parse-options"))
                {
                    m_defaultTestCase.processorOptions[*processorName].parseOptions = options->getFirstChild();
                }
                else if (options->getNodeName() == XalanDOMString("result-options"))
                {
                    m_defaultTestCase.processorOptions[*processorName].resultOptions = options->getFirstChild();
                }
                else if (options->getNodeName() == XalanDOMString("transform-options"))
                {
                    m_defaultTestCase.processorOptions[*processorName].transformOptions = options->getFirstChild();
                }

                options = options->getNextSibling();
            }
        }
        else if (currentNode->getNodeName() == XalanDOMString("testcases"))
        {
            // file-path
            const XalanNamedNodeMap* testCasesAttributes = currentNode->getAttributes();
            XalanNode * attributeNode = testCasesAttributes->getNamedItem(XalanDOMString("file-path"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE)
            {
                if (!m_testDirectory.empty())
                {
                    m_testDirectory += getPathSep();
                }
                m_testDirectory += attributeNode->getNodeValue();
            }
            // gold file-path
            attributeNode = testCasesAttributes->getNamedItem(XalanDOMString("gold-file-path"));
            if (attributeNode != 0 &&
                attributeNode->getNodeType() == XalanNode::ATTRIBUTE_NODE)
            {
                m_goldDirectory = attributeNode->getNodeValue();
            }
        }
        currentNode = currentNode->getNextSibling();
    }

    return true;
}



bool
Parameters::readTestCases(
    XalanFileUtility&   fileUtility,
    Logger&             logger)
{
    if (!fileUtility.checkDir(m_testDirectory))
    {
        logger.error() << "Invalid test directory: " << m_testDirectory.c_str() << endl;
        return false;
    }

    if (m_goldDirectory.empty())
    {
        logger.message() << "No gold directory specified" << endl;
        if (!fileUtility.checkDir(m_goldDirectory))
        {
            logger.warning() << "Invalid gold directory: " << m_goldDirectory.c_str() << endl;
        }
    }

    fileUtility.checkAndCreateDir(m_resultDirectory);

    typedef XalanFileUtility::FileNameVectorType FileNamesType;
    FileNamesType dirNames;

    fileUtility.getDirectoryNames(m_testDirectory, dirNames);

    FileNamesType::iterator dirIter = dirNames.begin();
    
    // for each test directory
    while (dirIter != dirNames.end())
    {
       
        FileNamesType xslTestFiles;
        fileUtility.getTestFileNames(m_testDirectory, *dirIter, true, xslTestFiles);

        FileNamesType::const_iterator xslIter = xslTestFiles.begin();

        // for each stylesheet
        while (xslIter != xslTestFiles.end())
        {
            // configure the stylesheet
            TestCase testCase = m_defaultTestCase;
            testCase.stylesheet = m_testDirectory;
            testCase.stylesheet += *dirIter;
            testCase.stylesheet += getPathSep();
            testCase.stylesheet += *xslIter;

            
            bool status = true;

            // configure the input document
            fileUtility.generateFileName(testCase.stylesheet, "xml", testCase.inputDocument, &status);
            if (status != true)
            {
                logger.warning() << "No matching input file for: " << testCase.stylesheet.c_str() << endl;
                ++xslIter;
                continue;
            }

            // configure result directory
            testCase.resultDirectory = m_resultDirectory;
            testCase.resultDirectory += *dirIter;
 
            // configure result document        
            XalanDOMString outFile = testCase.resultDirectory;
            outFile += getPathSep();
            outFile += *xslIter;

            fileUtility.generateFileName(outFile, "out", testCase.resultDocument);

            // configure gold result
            outFile = m_goldDirectory;
            outFile += getPathSep();
            outFile += *dirIter;
            outFile += getPathSep();
            outFile += *xslIter;

            status = true;
            fileUtility.generateFileName(outFile, "out", testCase.goldResult, &status);
            if (true == testCase.verifyResult && !status)
            {
                logger.warning() << "Verification on, but no matching gold file: " << testCase.goldResult.c_str() << endl;
            }

            m_testCases.push_back(testCase);
            
            ++xslIter;
        }

        ++dirIter;
    }

    return true;
}
