/*   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 common;

import org.apache.xmlbeans.*;

import javax.xml.namespace.QName;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import static org.junit.Assert.assertNotNull;

public class Common {
    public static final String NEWLINE = System.getProperty("line.separator");
    public static final String P = File.separator;

    public static String FWROOT = getRootFile();
    public static String CASEROOT = getCaseLocation();
    public static String XBEAN_CASE_ROOT = getCaseLocation() + P + "xbean";

    //location of files under "cases folder"
    public static String OUTPUTROOT = FWROOT + P + "build" + P + "test" + P + "output";


    public final List<XmlError> errorList = new LinkedList<>();
    public final XmlOptions xmOpts = new XmlOptions();

    public Common() {
        xmOpts.setErrorListener(errorList);
    }

    /**
     * If System.property for 'xbean.rootdir' == null
     * use '.' as basePath
     * '.' should be where the build.xml file lives
     */
    public static String getRootFile() throws IllegalStateException {
        String baseDir = System.getProperty("xbean.rootdir");
        if (baseDir == null) {
            return new File(".").getAbsolutePath();
        } else {
            return new File(baseDir).getAbsolutePath();
        }
    }

    /**
     * If System.property for 'cases.location' == null
     * use '.' as basePath and add src/test/resources.
     * should be where the build.xml file lives
     */
    public static String getCaseLocation() throws IllegalStateException {
        String baseDir = System.getProperty("cases.location");
        if (baseDir == null) {
            return new File("." + P + "src" + P + "test" + P + "resources").getAbsolutePath();
        } else {
            return new File(baseDir).getAbsolutePath();
        }
    }

    /**
     * Gets a case file from under CASEROOT with location passed in as strPath
     *
     * @return file Object for references location
     */
    public static File xbeanCase(String strPath) {
        return (new File(CASEROOT, strPath));
    }

    /**
     * Creates directory under output directory as noted by strPath
     *
     * @return File Object specified by strPath
     */
    public static File xbeanOutput(String strPath) {
        File result = (new File(OUTPUTROOT, strPath));
        File parentdir = result.getParentFile();
        parentdir.mkdirs();
        return result;
    }

    /**
     * Recursively deletes files under specified directory
     */
    public static void deltree(File dir) {
        if (dir.exists()) {
            if (dir.isDirectory()) {
                for (String s : Objects.requireNonNull(dir.list())) {
                    deltree(new File(dir, s));
                }
            }
            if (!dir.delete()) {
                System.out.println("Could not delete " + dir);
            }
            //throw new IllegalStateException("Could not delete " + dir);
        }
    }

    /**
     * check list of errors/warnings/msgs and print them. Return true if errors found
     */
    public static boolean printOptionErrMsgs(List<XmlError> errors) {
        boolean errFound = false;
        if (!errors.isEmpty()) {
            for (XmlError eacherr : errors) {
                int errSeverity = eacherr.getSeverity();
                if (errSeverity == XmlError.SEVERITY_ERROR) {
                    System.out.println("Err Msg (s) at line #" + eacherr.getLine() + ": " + eacherr.getMessage());
                    errFound = true;
                } else if (errSeverity == XmlError.SEVERITY_WARNING) {
                    System.out.println("Warning Msg (s) at line #" + eacherr.getLine() + ": " + eacherr.getMessage());
                } else if (errSeverity == XmlError.SEVERITY_INFO) {
                    System.out.println("Info Msg (s) at line #" + eacherr.getLine() + ": " + eacherr.getMessage());
                }
            }
            errors.clear();
        }
        return errFound;
    }

    /**
     * Validate schemas to instance based on the docType
     */
    public static void validateInstance(String[] schemas, String[] instances, QName docType) throws Exception {
        SchemaTypeLoader stl = makeSchemaTypeLoader(schemas);
        XmlOptions options = new XmlOptions();

        if (docType != null) {
            SchemaType docSchema = stl.findDocumentType(docType);
            assertNotNull(docSchema);
            options.setDocumentType(docSchema);
        }

        for (int i = 0; i < instances.length; i++) {
            XmlObject x = stl.parse(instances[i], null, options);

            //if (!startOnDocument) {
            //    XmlCursor c = x.newCursor();
            //    c.toFirstChild();
            //    x = c.getObject();
            //    c.dispose();
            //}

            List<XmlError> xel = new ArrayList<>();

            options.setErrorListener(xel);

            boolean isValid = x.validate(options);

            if (!isValid) {
                StringBuilder errorTxt = new StringBuilder("Invalid doc, expected a valid doc: ");
                errorTxt.append("Instance(").append(i).append("): ");
                errorTxt.append(x.xmlText());
                errorTxt.append("Errors: ");
                for (XmlError xmlError : xel) {
                    errorTxt.append(xmlError).append("\n");
                }
                System.err.println(errorTxt);
                throw new Exception("Instance not valid\n" + errorTxt);
            }
        }
    }

    /**
     * Convenience method to create a SchemaTypeLoader from a set of xsds
     */
    public static SchemaTypeLoader makeSchemaTypeLoader(String[] schemas)
        throws Exception {
        XmlObject[] schemaDocs = new XmlObject[schemas.length];

        for (int i = 0; i < schemas.length; i++) {
            schemaDocs[i] =
                XmlObject.Factory.parse(schemas[i]);
        }

        return XmlBeans.loadXsd(schemaDocs);
    }

    /**
     * Convenience class for creating tests in a multithreaded env
     */
    public static abstract class TestThread extends Thread {
        protected Throwable _throwable;
        protected boolean _result;
        protected XmlOptions xm;
        protected List<XmlError> errors = new ArrayList<>();

        public TestThread() {
            xm = new XmlOptions();
            xm.setErrorListener(errors);
            xm.setValidateOnSet();
        }

        public Throwable getException() {
            return _throwable;
        }

        public boolean getResult() {
            return _result;
        }


    }


}
