/*
 * Copyright (c) 2012, 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 - 2.6 - initial implementation
package org.eclipse.persistence.testing.jaxb.json.rootlevellist;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonWriter;
import jakarta.json.stream.JsonGenerator;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBMarshaller;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.oxm.json.JsonArrayBuilderResult;
import org.eclipse.persistence.oxm.json.JsonGeneratorResult;
import org.eclipse.persistence.testing.oxm.OXTestCase;

public class JsonObjectInArrayBuilderTestCases extends OXTestCase {

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

    public void testMarshalToArrayBuilderResult() throws Exception{
        JAXBContext ctx = JAXBContextFactory.createContext(new Class[]{WithoutXmlRootElementRoot.class}, null);
        Marshaller jsonMarshaller = ctx.createMarshaller();
        jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        jsonMarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);

        JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
        JsonArrayBuilderResult result = new JsonArrayBuilderResult(jsonArrayBuilder);


        WithoutXmlRootElementRoot foo = new WithoutXmlRootElementRoot();
        foo.setName("FOO");

        jsonMarshaller.marshal(foo, result);

        WithoutXmlRootElementRoot foo2 = new WithoutXmlRootElementRoot();
        foo.setName("FOO2");

        jsonMarshaller.marshal(foo, result);

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

        log(sw.toString());
        String controlString = "[{\"name\":\"FOO\"},{\"name\":\"FOO2\"}]";
        assertEquals(controlString, sw.toString());
    }

    public void testMarshalToGeneratorResult() throws Exception{
        JAXBContext ctx = JAXBContextFactory.createContext(new Class[]{WithoutXmlRootElementRoot.class}, null);
        Marshaller jsonMarshaller = ctx.createMarshaller();
        jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        jsonMarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);

        StringWriter sw = new StringWriter();
        JsonGenerator jsonGenerator = Json.createGenerator(sw);

        JsonGenerator arrayGenerator = jsonGenerator.writeStartArray();
        JsonGeneratorResult result = new JsonGeneratorResult(jsonGenerator);

        WithoutXmlRootElementRoot foo = new WithoutXmlRootElementRoot();
        foo.setName("FOO");
        jsonMarshaller.marshal(foo, result);

        WithoutXmlRootElementRoot foo2 = new WithoutXmlRootElementRoot();
        foo2.setName("FOO2");
        jsonMarshaller.marshal(foo2, result);

        jsonGenerator.writeEnd();
        jsonGenerator.flush();

        log(sw.toString());
        String controlString = "[{\"name\":\"FOO\"},{\"name\":\"FOO2\"}]";
        assertEquals(controlString, sw.toString());
    }

    public void testMarshalToArrayBuilderResultWithRoot() throws Exception{
        JAXBContext ctx = JAXBContextFactory.createContext(new Class[]{WithXmlRootElementRoot.class}, null);
        Marshaller jsonMarshaller = ctx.createMarshaller();
        jsonMarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);

        JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
        JsonArrayBuilderResult result = new JsonArrayBuilderResult(jsonArrayBuilder);

        WithXmlRootElementRoot foo = new WithXmlRootElementRoot();
        foo.setName("FOO");

        jsonMarshaller.marshal(foo, result);

        WithXmlRootElementRoot foo2 = new WithXmlRootElementRoot();
        foo2.setName("FOO2");
        jsonMarshaller.marshal(foo2, result);

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


        log(sw.toString());
        String controlString = "[{\"root\":{\"name\":\"FOO\"}},{\"root\":{\"name\":\"FOO2\"}}]";
        assertEquals(controlString, sw.toString());
    }

    public void testNestedResults() throws Exception{
        JAXBContext ctx = JAXBContextFactory.createContext(new Class[]{WithXmlRootElementRoot.class}, null);
        Marshaller jsonMarshaller = ctx.createMarshaller();
        jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        jsonMarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);

        StringWriter sw = new StringWriter();


        WithXmlRootElementRoot foo = new WithXmlRootElementRoot();
        foo.setName("FOO");

        WithXmlRootElementRoot foo2 = new WithXmlRootElementRoot();
        foo2.setName("FOO2");

        List<WithXmlRootElementRoot> foos = new ArrayList<WithXmlRootElementRoot>();
        foos.add(foo);
        foos.add(foo2);

        JsonGenerator generator = Json.createGenerator(sw);
        JsonGenerator arrayGenerator = generator.writeStartObject();
        JsonGeneratorResult nestedResult = new JsonGeneratorResult(arrayGenerator,"foosList");
        jsonMarshaller.marshal(foos, nestedResult);

        JsonGeneratorResult nestedSingleResult = new JsonGeneratorResult(generator,"singleThing");
        jsonMarshaller.marshal(foo, nestedSingleResult);

        generator.writeEnd(); //end root object
        generator.flush();

        log(sw.toString());
        String controlString = "{\"foosList\":[{\"name\":\"FOO\"},{\"name\":\"FOO2\"}],\"singleThing\":{\"name\":\"FOO\"}}";

        assertEquals(controlString, sw.toString());
    }


}
