import java.io.File;
import java.net.URL;
import java.util.GregorianCalendar;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import jaxb.Feed;

/**
 * Provides an interface to the feed document
 */
public class FeedModel {

    // Constant file reference to the feed document
    private final static File FEED_FILE = new File("feed.xml");

    // Constant file reference to your XSL style sheet
    private final static File XSL_SHEET = new File("xsl/atom-to-html.xsl");

    private static final Schema schema = loadSchema();
    private final Feed feed = null;
    private final Marshaller marshaller;

    /**
     * Default constructor
     */
    public FeedModel() {
        marshaller = createMarshaller(Feed.class, schema);

        // Unserialize XML data into new Java content trees
        // This will also validate the XML data when the schema is set
    }



    // TO DO Implement the functionality specified in the assignment



    /**
     * TO DO Test your implementation
     */
    public static void main(String[] args) {
        FeedModel model = new FeedModel();
    }



    /**
     * Get the current date and time as an instance of XMLGregorianCalendar.
     * This is necessary because the JAXB Binding Compiler converts `xs:date`
     * to `XMLGregorianCalendar` instead of `Data`.
     *
     * @return current date
     */
    private static XMLGregorianCalendar getXMLGregorianCalendarNow() {
        try {
            DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();

            return datatypeFactory.newXMLGregorianCalendar(
                new GregorianCalendar()
            );
        } catch (DatatypeConfigurationException ex) {
            throw new RuntimeException(
                "DatatypeFactory was not properly configured.", ex
            );
        }
    }

    /**
     * Loads and instantiates the projects XML Schema file
     *
     * @return reference to a Schema object
     */
    public static Schema loadSchema() {
        URL schemaFilePath = FeedModel.class.getResource("atom.xsd");

        try {
            return SchemaFactory
                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
                .newSchema(schemaFilePath);
        } catch (SAXException ex) {
            throw new RuntimeException("Error during schema parsing", ex);
        } catch (NullPointerException ex) {
            throw new RuntimeException("Could not load Atom schema", ex);
        })

    }

    /**
     * Creates a properly configured Marshaller for serializing XML
     *
     * @param type Class of the used Java object that is represented
     * @param schema Schema to validate against when writing
     * @return the marshaller
     */
    private static Marshaller createMarshaller(Class type, Schema schema) {
        try {
            JAXBContext context = JAXBContext.newInstance(type);
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            marshaller.setSchema(schema);
            
            // Add the xml-stylesheet processing instruction
            String xslDeclaration = "<?xml-stylesheet type=\"text/xsl\" href=\""
              + XSL_SHEET.toString() + "\"?>";
            marshaller.setProperty("com.sun.xml.internal.bind.xmlHeaders",
                xslDeclaration);

            return marshaller;
        } catch (JAXBException ex) {
            throw new RuntimeException("Could not create Marshaller.", ex);
        }
    }
}
