/*
 * Copyright (c) 2011, 2021 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 - February 20, 2013
package org.eclipse.persistence.testing.jaxb.xmlgregoriancalendar;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.testing.jaxb.JAXBWithJSONTestCases;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class XMLGregorianCalendarObjectTestCases extends JAXBWithJSONTestCases{

    private static final String CONTROL_XML_DOCUMENT;

    static {
        CONTROL_XML_DOCUMENT = "<?xml version = '1.0' encoding = 'UTF-8'?>" +
            "<root>" +
            "<thing xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:date\">1977-02-13</thing>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:date\">1977-02-13</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:date\">1982-05-30</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:time\">09:30:05</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:dateTime\">1985-09-23T10:33:05.001</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:dateTime\">1977-02-13T08:30:02.000</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:dateTime\">1977-02-13T08:30:02</things>" +
            "<things xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:dateTime\">2013-02-20T10:29:58"+TIMEZONE_OFFSET+"</things>" +
            "<gregCal>1985-09-23T10:33:05.001</gregCal>" +
            "<gregCalTime>09:30:05</gregCalTime>" +
            "</root>";
    }

    public XMLGregorianCalendarObjectTestCases(String name) throws Exception {
        super(name);
        setClasses(new Class[] {XMLGregorianCalendarHolder.class});
    }

    @Override
    protected Object getControlObject() {
        XMLGregorianCalendarHolder holder = new XMLGregorianCalendarHolder();
        DatatypeFactory factory;
        try {
            factory = DatatypeFactory.newInstance();
            Calendar calendar = Calendar.getInstance();
            calendar.clear();
            XMLGregorianCalendar cal = factory.newXMLGregorianCalendarDate(1977, 02, 13, DatatypeConstants.FIELD_UNDEFINED);
            XMLGregorianCalendar cal2 = factory.newXMLGregorianCalendarDate(1982, 5, 30, DatatypeConstants.FIELD_UNDEFINED);
            XMLGregorianCalendar cal3 = factory.newXMLGregorianCalendarTime(9, 30, 05, DatatypeConstants.FIELD_UNDEFINED);
            XMLGregorianCalendar cal4 = factory.newXMLGregorianCalendar(1985, 9, 23, 10, 33, 05, 1, DatatypeConstants.FIELD_UNDEFINED);
            XMLGregorianCalendar cal5 = factory.newXMLGregorianCalendar(1977, 02, 13, 8, 30, 2, 0, DatatypeConstants.FIELD_UNDEFINED);
            XMLGregorianCalendar cal6 = factory.newXMLGregorianCalendar(1977, 02, 13, 8, 30, 2, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);

            holder.thing = cal;
            holder.things = new ArrayList();
            holder.things.add(cal);
            holder.things.add(cal2);
            holder.things.add(cal3);
            holder.things.add(cal4);
            holder.things.add(cal5);
            holder.things.add(cal6);

            calendar.set(Calendar.MONTH, Calendar.FEBRUARY);
            calendar.set(Calendar.DAY_OF_MONTH, 20);
            calendar.set(Calendar.YEAR, 2013);
            calendar.set(Calendar.HOUR_OF_DAY, 10);
            calendar.set(Calendar.MINUTE, 29);
            calendar.set(Calendar.SECOND, 58);
            holder.things.add(calendar.getTime());

            holder.gregCal= cal4;
            holder.gregCalTime = cal3;
        } catch (DatatypeConfigurationException e) {
            e.printStackTrace();
            fail();
        }
        return holder;
    }

    @Override
    public boolean isUnmarshalTest() {
        return false;
    }

    @Override
    protected String getControlJSONDocumentContent() {
        return "{\"root\":{\n" +
                "   \"thing\":{\n" +
                "      \"type\":\"date\",\n" +
                "      \"value\":\"1977-02-13\"\n" +
                "   },\n" +
                "   \"things\":[{\n" +
                "      \"type\":\"date\",\n" +
                "      \"value\":\"1977-02-13\"\n" +
                "     },{\n" +
                "      \"type\":\"date\",\n" +
                "      \"value\":\"1982-05-30\"\n" +
                "     },{\n" +
                "      \"type\":\"time\",\n" +
                "      \"value\":\"09:30:05\"\n" +
                "     },{\n" +
                "      \"type\":\"dateTime\",\n" +
                "      \"value\":\"1985-09-23T10:33:05.001\"\n" +
                "     },\n" +
                "     {\n" +
                "      \"type\":\"dateTime\",\n" +
                "      \"value\":\"1977-02-13T08:30:02.000\"\n" +
                "     },\n" +
                "     {\n" +
                "      \"type\":\"dateTime\",\n" +
                "      \"value\":\"1977-02-13T08:30:02\"\n" +
                "     },    \n" +
                "     {\n" +
                "      \"type\":\"dateTime\",\n" +
                "      \"value\":\"2013-02-20T10:29:58"+TIMEZONE_OFFSET+"\"\n" +
                "     }\n" +
                "   ],\n" +
                "   \"gregCal\":\"1985-09-23T10:33:05.001\",\n" +
                "   \"gregCalTime\":\"09:30:05\"\n" +
                "}}";
    }

    @Override
    protected Document getControlDocument() {
        StringReader reader = new StringReader(CONTROL_XML_DOCUMENT);
        InputSource is = new InputSource(reader);
        Document doc = null;
        try {
            doc = parser.parse(is);
        } catch (Exception e) {
            fail("An error occurred setting up the control document");
        }
        return doc;
    }

    @Override
    public Object getReadControlObject() {
        XMLGregorianCalendarHolder holder = (XMLGregorianCalendarHolder)getControlObject();
        Date removed = (Date)holder.things.remove(6);
        DatatypeFactory factory;
        try {
            factory = DatatypeFactory.newInstance();
            XMLGregorianCalendar xmlGrelCal = factory.newXMLGregorianCalendar("2013-02-20T10:29:58-05:00");
            holder.things.add(xmlGrelCal);
        } catch (DatatypeConfigurationException e) {
            e.printStackTrace();
            fail();
        }
        return holder;
    }
}


