package dk.statsbiblioteket.doms.transformers.fileenricher;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.*;

import javax.xml.bind.*;

import dk.statsbiblioteket.doms.central.CentralWebservice;
import dk.statsbiblioteket.doms.central.InvalidCredentialsException;
import dk.statsbiblioteket.doms.central.InvalidResourceException;
import dk.statsbiblioteket.doms.central.MethodFailedException;
import dk.statsbiblioteket.doms.transformers.common.DomsConfig;
import dk.statsbiblioteket.doms.transformers.common.ObjectHandler;
import dk.statsbiblioteket.doms.transformers.fileenricher.autogenerated.BroadcastFileDescriptiveMetadataType;
import dk.statsbiblioteket.doms.transformers.fileenricher.autogenerated.ChannelIDsType;
import dk.statsbiblioteket.doms.transformers.fileenricher.autogenerated.ObjectFactory;

/**
 * Use DOMS to enrich file metadata.
 */
public class DomsFileEnricherObjectHandler implements ObjectHandler {

    private final DomsConfig config;
    private final CentralWebservice webservice;
    private Marshaller marshaller;
    private ObjectHandler delegate;
    private MuxFileChannelCalculator channelCalc;

    /**
     * Initialise object handler.
     *
     * @param config     Configuration.
     * @param webservice The DOMS WebService.
     */
    public DomsFileEnricherObjectHandler(FileEnricherConfig config, CentralWebservice webservice, ObjectHandler delegate)
            throws JAXBException, IOException, ParseException, URISyntaxException {
        this.config = config;
        this.webservice = webservice;
        marshaller = JAXBContext.newInstance("dk.statsbiblioteket.doms.transformers.fileenricher.autogenerated").createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        File csv = new File(Thread.currentThread().getContextClassLoader().getResource("muxChannels.csv").toURI());
        channelCalc = new MuxFileChannelCalculator(csv);
    }

    @Override
    public void transform(String uuid) throws Exception {

        webservice.markInProgressObject(Arrays.asList(uuid), "Modifying object as part of datamodel upgrade");
        if (delegate != null) {
            delegate.transform(uuid);
        }
        String filename = getFilenameFromObject(uuid);
        BroadcastFileDescriptiveMetadataType metadata = decodeFilename(filename);
        storeMetadataInObject(uuid, metadata);
        webservice.markPublishedObject(Arrays.asList(uuid), "Modifying object as part of datamodel upgrade");
    }

    public void storeMetadataInObject(String uuid, BroadcastFileDescriptiveMetadataType metadata) throws InvalidCredentialsException, MethodFailedException, InvalidResourceException, JAXBException {
        StringWriter writer = new StringWriter();
        JAXBElement<BroadcastFileDescriptiveMetadataType> blob = new ObjectFactory().createBroadcastFileDescriptiveMetadata(metadata);
        marshaller.marshal(blob, writer);
        String contents = writer.toString();
        webservice.modifyDatastream(uuid, "BROADCAST_METADATA", contents, "Updating metadata as part of the radio/tv datamodel refactoring");
    }

    public String getFilenameFromObject(String uuid) throws InvalidCredentialsException, MethodFailedException, InvalidResourceException {
        String label = webservice.getObjectProfile(uuid).getTitle();
        String filename = label.substring(label.lastIndexOf("/") + 1);
        return filename;
    }

    public BroadcastFileDescriptiveMetadataType decodeFilename(String filename) {
        if (filename.endsWith(".ts")) {
            return decodeMuxFilename(filename);
        } else if (filename.endsWith(".wav")) {
            return decodeRadioFilename(filename);
        } else if (filename.endsWith(".mpeg")) {
            return decodeMpegFilename(filename);
        } else {
            return null;
        }
    }

    //TODO: get fixed channel list for Mux1 and mux2
    private BroadcastFileDescriptiveMetadataType decodeMuxFilename(String filename) {
        //mux1.1287514800-2010-10-19-21.00.00_1287518400-2010-10-19-22.00.00_dvb1-1.ts
        //(type).(timestart)-(timestart)_(timeend)-(timeEnd)_(recorder).ts
        BroadcastFileDescriptiveMetadataType metadata = new BroadcastFileDescriptiveMetadataType();

        int mux = Integer.parseInt(filename.split("\\.")[0].substring(3));

        String startUnixTime = filename.split("\\.")[1].split("-")[0];
        String stopUnixTime = filename.split("_")[1].split("-")[0];
        String recorder = filename.split("_")[2].split("\\.")[0];

        metadata.setStartTimeDate(CalendarUtils.getXmlGregorianCalendar(startUnixTime));
        metadata.setEndTimeDate(CalendarUtils.getXmlGregorianCalendar(stopUnixTime));
        metadata.setRecorder(recorder);


        ChannelIDsType channels = new ChannelIDsType();

        List<String> channelIDs = channelCalc.getChannelIDsForMux(mux, metadata.getStartTimeDate().toGregorianCalendar().getTime());

        for (String channelID : channelIDs) {
            channelID = ChannelIDToSBChannelIDMapper.getInstance().mapToSBChannelID(channelID);
            channels.getChannel().add(channelID);
        }
        metadata.setChannelIDs(channels);
        return metadata;
    }

    private BroadcastFileDescriptiveMetadataType decodeRadioFilename(String filename) {
        //drp1_88.100_DR-P1_pcm_20080509045602_20080510045501_encoder5-2.wav
        //(channelID)_(frequency)_(CHANNELID)_(format)_(timeStart)_(timeEnd)_(recorder).wav
        return null;

    }

    private BroadcastFileDescriptiveMetadataType decodeMpegFilename(String filename) {
        //tv2c_623.250_K40-TV2-Charlie_mpeg1_20080503121001_20080504030601_encoder3-2.mpeg
        //kanal4_359.250_K42-Kanal4_mpeg1_20101023195601_20101023231601_encoder7-2.mpeg
        //tv3_161.250_S09-TV3_mpeg1_20101021175601_20101022010602_encoder6-2.mpeg
        //(channelID)_(frequency)_(CHANNELID)_(format)_(timeStart)_(timeEnd)_(recorder).mpeg
        return null;
    }


}

@@ -1658,24 +1658,58 @@
 webservice;%0A
+        this.delegate = delegate;%0A
         mars

Store the given delegate