package de.lcs.wep.rest.request.post.xml;

import com.google.api.client.util.DateTime;
import de.lcs.wep.calendar.Event;
import de.lcs.wep.rest.AClient;
import de.lcs.wep.rest.Constants;
import de.lcs.wep.rest.request.post.APostRoomSchedule;
import de.lcs.wep.rest.request.post.IPostRequest;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by Sönke Greve on 23.10.2014.
 */
public class XmlPostRoomSchedule extends APostRoomSchedule implements IPostRequest {

    private String strState;
    private String strSubState;
    private SimpleDateFormat timeFormat;
    private SimpleDateFormat dateFormat;
    private boolean useAlias;

    public XmlPostRoomSchedule(AClient client, String labelID, String roomName, List<Event> events, boolean useAlias, String template) {
        super(client, labelID, roomName, events, template);
        strState = "";
        strSubState = "";
        timeFormat = new SimpleDateFormat("HH:mm");
        dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        this.useAlias = useAlias;
    }

    @Override
    public String getContentType() {
        return Constants.ContentType.XML.toString();
    }

    @Override
    public String getContent() {

        // creates the xml string containing placeholders (%s, %n ...) to be replaced with the calendars values
        List<Event> events = super.getEvents();
        String rawXml = createRawXml(events);

        String xmlLabelID = StringEscapeUtils.escapeXml11(super.getLabelID());
        String xmlRoomName = StringEscapeUtils.escapeXml11(super.getRoomName());
        String xmlTemplate = StringEscapeUtils.escapeXml11(super.getTemplate());

        updateStateFields(events);
        String xmlState = StringEscapeUtils.escapeXml11(strState);
        String xmlSubState = StringEscapeUtils.escapeXml11(strSubState);

        //String result = String.format(rawXml, xmlRoomName, xmlLabelID, xmlLabelID, xmlTemplate, xmlRoomName, xmlState, xmlSubState);
        String result = String.format(rawXml, xmlRoomName, xmlLabelID, xmlLabelID, xmlTemplate, xmlRoomName);
        return result;
    }

    private String createRawXml(List<Event> events) {
        String raw = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
                "<TaskOrder title=\"Show schedule of room %s on label %s\">" + // roomname, labelID
                "<TemplateTask labelId=\"%s\" externalId=\"1\" template=\"%s\">" + // labelID, template
                "<room roomName=\"%s\">"; // roomname

        // Code for different record xmls
        //"<room name=\"%s\" state=\"%s\" substate=\"%s\">"; // roomname, state, substate
        //raw += createEventsXml(events);

        raw += createLancomEventsXml(events);
        raw += "</room></TemplateTask></TaskOrder>";
        return raw;
    }

//    /**
//     * Creates an xml-element 'room' formatted as follows:
//     * <p/>
//     * <room name="Room YELLOW" state="Belegt" substate="bis 15:00 Uhr">
//     * <day date="Heute">
//     * <event>
//     * <subject>Sprint Planning Teil 2</subject>
//     * <owner>Max Mustermann</owner>
//     * <start>13:30</start>
//     * <end>15:00</end>
//     * </event>
//     * <event>
//     * <subject>Title 2</subject>
//     * <owner>Postfach Bewerbungen</owner>
//     * <start>17:30</start>
//     * <end>18:30</end>
//     * </event>
//     * <event>
//     * <subject>Title 3</subject>
//     * <owner>Micheal Jackson</owner>
//     * <start>09:00</start>
//     * <end>10:00</end>
//     * </event>
//     * </day>
//     * <day date="Morgen">
//     * <event>
//     * <subject>Title 4</subject>
//     * <owner>Postfach Bewerbungen</owner>
//     * <start>10:00</start>
//     * <end>11:00</end>
//     * </event>
//     * <event>
//     * <subject>Title 5</subject>
//     * <owner>Phil Collins</owner>
//     * <start>12:30</start>
//     * <end>13:00</end>
//     * </event>
//     * </day>
//     * </room>
//     *
//     * @param events
//     * @return
//     */
//    private String createEventsXml(List<Event> events) {
//        String result = "";
//        Date prev = null;
//        for (Event e : events) {
//            Date cur = new Date(e.getStart().getValue());
//
//            /* Yeah, I know this could be done properly using the Java's DOM capabilities. This was faster. */
//
//            // first entry
//            if (prev == null) {
//                result = "<day date=\"" + createDateString(cur) + "\">";
//            }
//
//            // new day
//            if (prev != null && cur != null && !DateUtils.isSameDay(prev, cur)) {
//                result += "</day><day date=\"" + createDateString(cur) + "\">";
//            }
//
//            // contents of the day
//            String subject = e.getSubject();
//            String owner = e.getOwner();
//            String start = getTimeString(e.getStart());
//            String end = getTimeString(e.getEnd());
//            result += "<event><subject>" + subject + "</subject><owner>" + owner + "</owner><start>" + start + "</start><end>" + end + "</end></event>";
//
//            // remember the current day for the next loop
//            prev = cur;
//        }
//        result += "</day>";
//        return result;
//    }

    /**
     * Creates an xml-element 'room' formatted as follows:
     * <p/>
     * <room roomName="Raum Test">
     * <field key="date" value="13.04.2015"/>
     * <field key="time1" value="09:00 - 15:00"/>
     * <field key="purpose1" value="ePaper Test"/>
     * <field key="chair1" value="LANCOM"/>
     * <field key="time2" value="14.04.2015"/>
     * <field key="purpose2" value="Scrum of Scrums"/>
     * <field key="chair2" value="Max Mustermann"/>
     * </room>
     *
     * @param events
     * @return
     */
    private String createLancomEventsXml(List<Event> events) {

        if (events == null || events.size() < 1) {
            return "";
        }

        String template = "<field key=\"date\" value=\"%s\"/>" +
                "<field key=\"time1\" value=\"%s\"/>" +
                "<field key=\"purpose1\" value=\"%s\"/>" +
                "<field key=\"chair1\" value=\"%s\"/>" +
                "<field key=\"time2\" value=\"%s\"/>" +
                "<field key=\"purpose2\" value=\"%s\"/>" +
                "<field key=\"chair2\" value=\"%s\"/>";

        // extract data from first event
        Event e1 = events.get(0);
        Date d1 = new Date(e1.getStart().getValue());
        String date = createDateString(d1);
        String time1 = getTimeString(e1.getStart()) + " - " + getTimeString(e1.getEnd());
        String purpose1 = e1.getSubject();
        if (purpose1 == null || purpose1.isEmpty()) {
            purpose1 = "[No title defined]";
        }
        String chair1 = e1.getOwner();

        // extract data from second event if available
        String time2 = "";
        String purpose2 = "";
        String chair2 = "";
        if (events.size() > 1) {
            Event e2 = events.get(1);
            Date d2 = new Date(e2.getStart().getValue());
            // next event is on the same day show it on the display
            if (DateUtils.isSameDay(d1, d2)) {
                time2 = getTimeString(e2.getStart()) + " - " + getTimeString(e2.getEnd());
                purpose2 = e2.getSubject();
                if (purpose2 == null || purpose2.isEmpty()) {
                    purpose2 = "[No title defined]";
                }
                chair2 = e2.getOwner();
            }
        }

        // format the result and return it
        String result = String.format(template, date, time1, purpose1, chair1, time2, purpose2, chair2);
        return result;
    }

    private String createDateString(Date date) {
        Date today = new Date();
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 1);
        Date tomorrow = cal.getTime();

        String result = dateFormat.format(date);
        if (useAlias) {
            if (DateUtils.isSameDay(today, date)) {
                result = "Heute";
            } else if (DateUtils.isSameDay(tomorrow, date)) {
                result = "Morgen";
            }
        }
        return result;
    }

    private String getTimeString(DateTime dt) {
        Date d = new Date(dt.getValue());
        String result = timeFormat.format(d);
        return result;
    }

    private void updateStateFields(List<Event> events) {

        if (events.size() < 1) {
            strState = ROOM_STATE.FREE.toString();
            strSubState = "";
        } else {

           /*
             * 2 cases - the current DateTime is
             * - BEFORE the first event
             * - IN the first event
             */

            Event firstEvent = events.get(0);

            long now = new Date().getTime();
            long start = firstEvent.getStart().getValue();
            long end = firstEvent.getEnd().getValue();

            boolean isOccupied = false;
            if (start <= now && now <= end) {
                isOccupied = true;
            }

            if (!isOccupied) {
                // find the start date
                strState = ROOM_STATE.FREE.toString();
                strSubState = "bis " + getTimeString(events.get(0).getStart()) + " Uhr";
            } else {
                strState = ROOM_STATE.OCCUPIED.toString();
                strSubState = createSubState(events);
            }
        }
    }

    private String createSubState(List<Event> events) {
        Event firstEvent = events.get(0);

        // find the first free slot -  or the lastBeforeFree date's end
        Event lastBeforeFree = firstEvent;
        for (Event e : events) {
            // skip the first event
            if (e.getId().equals(firstEvent.getId())) {
                continue;
            }

            // get the first event after that a free slot is available
            if (lastBeforeFree.getEnd().getValue() == e.getStart().getValue()) {
                lastBeforeFree = e;
            } else {
                break;
            }
        }

        // check if lastBeforeFree is the last event in the event list
        String strTime = getTimeString(lastBeforeFree.getEnd());
        Event lastEvent = events.get(events.size() - 1);

        String result = "";
        if (lastEvent.getId().equals(lastBeforeFree.getId())) {
            result = "bis mindestens " + strTime + " Uhr";
        } else {
            result = "bis " + strTime + " Uhr";
        }
        return result;
    }
}
