/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Denise Smith - August 2011 - 2.4 - Initial implementation
package org.eclipse.persistence.testing.jaxb.json;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonWriter;
import jakarta.json.JsonWriterFactory;
import jakarta.json.stream.JsonGenerator;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.json.JsonArrayBuilderResult;
import org.eclipse.persistence.oxm.json.JsonGeneratorResult;
import org.eclipse.persistence.oxm.json.JsonObjectBuilderResult;
import org.eclipse.persistence.testing.oxm.OXTestCase;

public abstract class JSONTestCases extends OXTestCase{
    protected JAXBContext jaxbContext;
    protected Marshaller jsonMarshaller;
    protected Unmarshaller jsonUnmarshaller;
    protected ClassLoader classLoader;
    protected XMLContext xmlContext;

    protected String controlJSONLocation;
    private String controlJSONWriteLocation;

    public JSONTestCases(String name) {
        super(name);
    }

    public void setUp() throws Exception{
        try {
            super.setUp();
            jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
            jsonUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");

        } catch (Exception e) {
            e.printStackTrace();
            fail("An error occurred during setup");
        }
    }

    public void setControlJSON(String location) {
        this.controlJSONLocation = location;
    }

    public void setWriteControlJSON(String location) {
        this.controlJSONWriteLocation = location;
    }

    public String getWriteControlJSON(){
        if(controlJSONWriteLocation != null){
            return controlJSONWriteLocation;
        }else{
            return controlJSONLocation;
        }
    }

    abstract protected Object getControlObject();

    /*
     * Returns the object to be used in a comparison on a read
     * This will typically be the same object used to write
     */
    public Object getReadControlObject() {
        return getControlObject();
    }

    /*
     * Returns the object to be written to XML which will be compared
     * to the control document.
     */
    public Object getWriteControlObject() {
        return getControlObject();
    }

    public Map getProperties(){
        return null;
    }

    public void setClasses(Class[] newClasses) throws Exception {
        classLoader = Thread.currentThread().getContextClassLoader();
        jaxbContext = JAXBContextFactory.createContext(newClasses, getProperties(), classLoader);
        xmlContext = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext();
        jsonMarshaller = jaxbContext.createMarshaller();
        jsonUnmarshaller = jaxbContext.createUnmarshaller();
    }
    public void jsonToObjectTest(Object testObject) throws Exception {
        jsonToObjectTest(getReadControlObject(), testObject);
    }

    public void jsonToObjectTest(Object control, Object testObject) throws Exception {
        log("\n**jsonToObjectTest**");
        log("Expected:");
        log(control.toString());
        log("Actual:");
        log(testObject.toString());

        if ((getReadControlObject() instanceof JAXBElement) && (testObject instanceof JAXBElement)) {
            JAXBElement controlObj = (JAXBElement)control;
            JAXBElement testObj = (JAXBElement)testObject;
            compareJAXBElementObjects(controlObj, testObj);
        } else {

            if(testObject instanceof Collection && control instanceof Collection){
                Collection testCollection = (Collection)testObject;
                Collection controlCollection = (Collection)control;
                assertTrue(testCollection.size() == controlCollection.size());
                Iterator testIter = testCollection.iterator();
                Iterator controlIter = controlCollection.iterator();
                while(controlIter.hasNext()){
                    assertEquals(controlIter.next(), testIter.next());
                }
            }else{

               assertEquals(control, testObject);
            }
        }
    }


    protected void compareStringToControlFile(String test, String testString) {

        compareStringToFile(test, testString,getWriteControlJSON(), true);
    }

    protected void compareStringToFile(String test, String testString, String writeControlJSON, boolean removeWhitespace) {
        String expectedString = loadFileToString(writeControlJSON);
        compareStrings(test, testString, expectedString, removeWhitespace);
    }

    protected void compareStrings(String test, String testString, String expectedString, boolean removeWhitespace) {
        log(test);
        log("Expected (With All Whitespace Removed):");
        if(removeWhitespace){
           expectedString = expectedString.replaceAll("[ \b\t\n\r ]", "");
        }
        log(expectedString);

        log("\nActual (With All Whitespace Removed):");
        if(removeWhitespace){
            testString = testString.replaceAll("[ \b\t\n\r]", "");
        }
        log(testString);
        assertEquals(expectedString, testString);
    }

    public void testObjectToJSONStringWriter() throws Exception {
        StringWriter sw = new StringWriter();
        jsonMarshaller.marshal(getWriteControlObject(), sw);
        compareStringToControlFile("**testObjectToJSONStringWriter**", sw.toString());
    }

     public void testJSONMarshalToOutputStream() throws Exception{
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            jsonMarshaller.marshal(getWriteControlObject(), os);
            compareStringToControlFile("testJSONMarshalToOutputStream", new String(os.toByteArray()));
            os.close();
        }

     public void testJSONMarshalToBuilderResult() throws Exception{
           Object writeControlObject = getWriteControlObject();
           if(writeControlObject instanceof Collection || writeControlObject.getClass().isArray()){
               marshalToArrayBuilderResult();
           }else{
               marshalToObjectBuilderResult();
           }
     }

       public void marshalToObjectBuilderResult() throws Exception{

            JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
            JsonObjectBuilderResult result = new JsonObjectBuilderResult(jsonObjectBuilder);
            jsonMarshaller.marshal(getWriteControlObject(), result);

            JsonObject jsonObject = jsonObjectBuilder.build();
            StringWriter sw = new StringWriter();

            JsonWriter writer= Json.createWriter(sw);
            writer.writeObject(jsonObject);
            writer.close();
            log(sw.toString());
            compareStringToControlFile("**testJSONMarshalToBuilderResult**", sw.toString());
        }

    public void marshalToArrayBuilderResult() throws Exception{

           JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
           JsonArrayBuilderResult result = new JsonArrayBuilderResult(jsonArrayBuilder);
           jsonMarshaller.marshal(getWriteControlObject(), result);

           JsonArray jsonArray = jsonArrayBuilder.build();
           StringWriter sw = new StringWriter();
           JsonWriter writer= Json.createWriter(sw);
           writer.writeArray(jsonArray);
           writer.close();

           log(sw.toString());
           compareStringToControlFile("**testJSONMarshalToBuilderResult**", sw.toString());
       }

    public void testJSONMarshalToGeneratorResult() throws Exception{

        StringWriter sw = new StringWriter();
        JsonGenerator jsonGenerator = Json.createGenerator(sw);
        JsonGeneratorResult result = new JsonGeneratorResult(jsonGenerator);
        jsonMarshaller.marshal(getWriteControlObject(), result);
        jsonGenerator.flush();

        log(sw.toString());
        compareStringToControlFile("**testJSONMarshalToGeneratorResult**", sw.toString());
    }

     public void testJSONMarshalToOutputStream_FORMATTED() throws Exception{
        jsonMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        jsonMarshaller.marshal(getWriteControlObject(), os);
        compareStringToFile("testJSONMarshalToOutputStream", new String(os.toByteArray()), getWriteControlJSONFormatted(), shouldRemoveWhitespaceFromControlDocJSON());
        os.close();
    }

    public void testJSONMarshalToStringWriter() throws Exception{
        StringWriter sw = new StringWriter();
        jsonMarshaller.marshal(getWriteControlObject(), sw);
        compareStringToControlFile("**testJSONMarshalToStringWriter**", sw.toString());
    }

    public void testJSONMarshalToStringWriter_FORMATTED() throws Exception{
        jsonMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter sw = new StringWriter();
        jsonMarshaller.marshal(getWriteControlObject(), sw);
        compareStringToFile("**testJSONMarshalToStringWriter**", sw.toString(), getWriteControlJSONFormatted(), shouldRemoveWhitespaceFromControlDocJSON());
    }

    protected String getWriteControlJSONFormatted(){
        return getWriteControlJSON();
    }

    protected boolean shouldRemoveWhitespaceFromControlDocJSON(){
        return true;
    }
}
