/*
 * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
 */

package javasoft.sqe.tests.bind.binder;

import java.util.Map;
import java.util.LinkedHashMap;
import jakarta.xml.bind.Binder;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import org.w3c.dom.Node;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.util.ValidationEventCollector;
import jakarta.xml.bind.PropertyException;
import javasoft.sqe.javatest.Status;
import java.io.PrintWriter;
import javasoft.sqe.tests.api.jakarta.xml.bind.CTTest;

public class SetGet_CTTests extends CTTest {

    /**
     * Command line starter.
     */
    public static void main(String[] args) {
        SetGet_CTTests test = new SetGet_CTTests();
        PrintWriter err = new PrintWriter(System.err, true);
        PrintWriter out = new PrintWriter(System.out, true);
        Status status = test.run(args, err, out);
        err.flush();
        out.flush();
        status.exit();
    }

    public static final String[] SUPPORTED_PROPERTY_NAMES = new String[]{
            "jaxb.encoding",
            "jaxb.formatted.output",
            "jaxb.schemaLocation",
            "jaxb.noNamespaceSchemaLocation",
            "jaxb.fragment"
        };
    public static final String NOT_SUPPORTED_PROPERTY = "__!not_supported_by_jaxbimpl???";
    public static final Object[] SAMPLE_SUPPORTED_PROPERTY_VALUES = new Object[]{
            "UTF-8",
            Boolean.TRUE,
            "schema-location",
            "no-namespace-schema-location",
            Boolean.TRUE
        };

    public Binder<Node> getBinder() throws JAXBException{
		JAXBContext jaxbContext = getJAXBContext();
		return jaxbContext.createBinder();
	}

    public Status SetGet001( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
        try {
            if(binder.getEventHandler() == null){
                return Status.failed("Binder.getEventHandler() returns null");
            }
            return Status.passed("Binder.getEventHandler() returns default event handler - Ok");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Binder.getEventHandler has thrown an exception: "+e);
        }
    }

    public Status SetGet002( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
        ValidationEventHandler validationEventHandler = new ValidationEventCollector();
        try {
            binder.setEventHandler(validationEventHandler);
            ref.println("Binder.setEventHandler(new ValidationEventCollector()) - ok");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Binder.setEventHandler() has thrown an exception "+e);
        }
        try {
            if(binder.getEventHandler() == null){
                return Status.failed("Binder.getEventHandler() returns null after validation event handler has been set");
            }
            return Status.passed("Binder.getEventHandler() returns non-null value - ok");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Binder.getEventHandler() has thrown an exception: "+e);
        }
    }

    public Status SetGet003( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
        try {
            binder.setEventHandler(null);
            ref.println("Binder.setEventHandler(null) - ok");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Binder.setEventHandler(null) has thrown an exception "+e);
        }
        try{
            if(binder.getEventHandler() == null){
                return Status.failed("Binder.getEventHandler() returns null after validation event handler has been unset");
            }
            return Status.passed("Binder.getEventHandler() returns non-null value - ok");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Binder.getEventHandler() has thrown an exception: "+e);
        }
    }

    public Status SetGet004( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
        try{
            binder.getProperty(null);
            return Status.failed("Binder.getProperty(null) should throw IllegalArgumentException");
        }catch(PropertyException pe){
            return Status.failed("Binder.getProperty(null) has thrown PropertyException but should throw IllegalArgumentException");
        }catch(IllegalArgumentException ie){
            //ok
            return Status.passed("Binder.getProperty(null) has thrown an IllegalArgumentException - ok");
        }
    }

    public Status SetGet005( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }

        LinkedHashMap<String,PropertyException> unsupportedRequiredProperties = new LinkedHashMap<String,PropertyException>();

        for(String property:SUPPORTED_PROPERTY_NAMES){
            try {
                binder.getProperty(property);
                ref.println("Binder.getProperty(\""+property+"\") - ok");
            } catch (PropertyException e) {
                unsupportedRequiredProperties.put(property,e);
            }
        }
        if(!unsupportedRequiredProperties.isEmpty()){
            StringBuffer buffer = new StringBuffer();
            buffer.append('[');
            for(Map.Entry<String,PropertyException> e:unsupportedRequiredProperties.entrySet()){
                String property = e.getKey();
                ref.println(property);
                e.getValue().printStackTrace(ref);
                buffer.append(property).append(',');
            }
            buffer.setLength(buffer.length()-1);
            buffer.append(']');
            return Status.failed("Unexpected PropertyException on getting following properties: "+buffer);
        }
        return Status.passed("Ok");
    }

    public Status SetGet006( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
        try {
            binder.getProperty(NOT_SUPPORTED_PROPERTY);
            return Status.failed("PropertyException is not thrown from Binder.getProperty(\""+NOT_SUPPORTED_PROPERTY+"\")");
        } catch (PropertyException e) {
            //ok
            return Status.passed("Bunder.getProperty(\""+NOT_SUPPORTED_PROPERTY+"\") has thrown PropertyException - ok");
        }
    }

    public Status SetGet007( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }

        try{
            binder.setProperty(null,"-");
            return Status.failed("Binder.setProperty(null,someValue) should throw IllegalArgumentException");
        }catch(PropertyException pe){
            return Status.failed("Binder.setProperty(null,someValue) has thrown PropertyException but should throw IllegalArgumentException");
        }catch(IllegalArgumentException ie){
            //ok
            return Status.passed("Binder.setProperty(null,someValue) has thrown an IllegalArgumentException - ok");
        }
    }

    public Status SetGet008( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }

        LinkedHashMap<Integer,PropertyException> indexToException = new LinkedHashMap<Integer,PropertyException>();
        for(int i = 0; i<SUPPORTED_PROPERTY_NAMES.length;i++){
            try {
                binder.setProperty(SUPPORTED_PROPERTY_NAMES[i],SAMPLE_SUPPORTED_PROPERTY_VALUES[i]);
                ref.println("Binder.setProperty(\""+SUPPORTED_PROPERTY_NAMES[i]+"\","+SAMPLE_SUPPORTED_PROPERTY_VALUES[i]+") - ok");
            } catch (PropertyException e) {
                indexToException.put(i,e);
            }
        }

        if(!indexToException.isEmpty()){
            StringBuffer buffer = new StringBuffer();
            buffer.append('[');
            for(Map.Entry<Integer,PropertyException> e: indexToException.entrySet()){
                int index = e.getKey().intValue();
                String property = SUPPORTED_PROPERTY_NAMES[index];
                Object value = SAMPLE_SUPPORTED_PROPERTY_VALUES[index];
                ref.println(property);
                e.getValue().printStackTrace(ref);
                buffer.append(property).append('=').append(SAMPLE_SUPPORTED_PROPERTY_VALUES[index]).append(',');
            }
            buffer.setLength(buffer.length()-1);
            buffer.append(']');
            return Status.failed("Unexpected PropertyException on setting following properties: "+buffer);
        }
        return Status.passed("Ok");
    }

    public Status SetGet009( ) {
        Binder<Node> binder;
        try {
            binder = getBinder();
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }

        try {
            binder.setProperty(NOT_SUPPORTED_PROPERTY,"-");
            return Status.failed("PropertyException is not thrown from Binder.setProperty(\""+NOT_SUPPORTED_PROPERTY+"\",\"-\")");
        } catch (PropertyException e) {
            return Status.passed("Bunder.setProperty(\""+NOT_SUPPORTED_PROPERTY+"\",\"-\") has thrown PropertyException - ok");
        }
    }

    public Status SetGet_Schema001( ) {
        try {
            Binder<Node> binder = getBinder();
            if( binder.getSchema() != null )
                return Status.failed( "Binder.getSchema() initial value isn't null" );
            binder.setSchema( schema );
            if( !schema.equals( binder.getSchema() ) )
                return Status.failed( "Binder.getSchema() isn't equal to a schema that set right before" );
            binder.setSchema( null );
            if( binder.getSchema() != null )
                return Status.failed( "Binder.getSchema() isn't null after 'binder.setSchema( null )'" );
            return Status.passed("OK");
        } catch (JAXBException e) {
            e.printStackTrace(ref);
            return Status.failed("Unable to create valid context or binder");
        }
    }


}

