/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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 scomp.common;

import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlOptions;
import org.junit.Before;

import java.util.ArrayList;

public class BaseCase {
    protected boolean bVerbose = true;

    protected XmlOptions validateOptions;
    protected ArrayList errorList;

    @Before
    public void setUp() {
        validateOptions = new XmlOptions();
        errorList = new ArrayList();
        validateOptions.setErrorListener(errorList);
    }

    protected void clearErrors() {
        //reset error list for next time
        errorList = new ArrayList();
        validateOptions.setErrorListener(errorList);
    }

    public void showErrors() {
        if (bVerbose)
            for (int i = 0; i < errorList.size(); i++) {
                XmlError error = (XmlError) errorList.get(i);
                System.out.println("\n");
                System.out.println("Message: " + error.getMessage() + "\n");
                if (error.getCursorLocation() != null)
                    System.out.println("Location of invalid XML: " +
                            error.getCursorLocation().xmlText() + "\n");
            }

    }

    //TODO: compare regardless of order
    public boolean compareErrorCodes(String[] expected) {
        if ( errorList.size() != expected.length){
            System.err.println(stringOfCodes(expected,errorList));
                           
           return false;
        }
        StringBuilder errMessage = new StringBuilder();
        for (int i = 0; i < errorList.size(); i++) {
            XmlError error = (XmlError) errorList.get(i);
            if ( error.getErrorCode() == null )
              errMessage.append("Kevin needs a code here "+error.getMessage()+"\n");

            if (!expected[i].equals(error.getErrorCode())){
                if (errMessage.length() > 0)
                    System.err.println(errMessage);
                ArrayList exp=new ArrayList();

                System.err.println(stringOfCodes(expected,errorList));
                return false;
            }
        }
        return true;
    }

    public String stringOfCodes(String[] errorCodes, ArrayList actual_errorCodes)
    {
        StringBuilder res = new StringBuilder();
        res.append("\n Expected codes:\n");
        int i=0;
        for (;i < errorCodes.length; i++ )
            res.append( errorCodes[i]+"\n" );
        res.append("\nBut Got: \n");
        for ( i=0 ;i < actual_errorCodes.size(); i++ )
            res.append( actual_errorCodes.get(i)+"\n" );

        return res.toString();
    }

}
