package de.lcs.wep.service.update;

import de.lcs.wep.calendar.Event;
import de.lcs.wep.rest.response.LabelInfo;
import de.lcs.wep.service.WePService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sgreve on 31.03.2015.
 */
public class TagUpdater {

    private static Logger logger = LogManager.getLogger(TagUpdater.class);

    String tag;
    List<Event> events;
    Map<String, LabelUpdate> labelIdToUpdate;

    public TagUpdater(String tag) {
        this.tag = tag;
        events = null;
        labelIdToUpdate = new HashMap<String, LabelUpdate>();
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public void addLabel(LabelInfo labelInfo) {
        if (!labelIdToUpdate.containsKey(labelInfo.getLabelId())) {
            LabelUpdate lup = new LabelUpdate(labelInfo);
            labelIdToUpdate.put(labelInfo.getLabelId(), lup);
        }
    }

    public void removeLabel(LabelInfo li) {
        labelIdToUpdate.remove(li.getLabelId());
    }

    public boolean update(String roomName, List<Event> events, WePService service) throws Exception {

        logger.info("Updating tag [" + tag + "]");
        boolean isEventListEqual = isEventListEqual(this.events, events);
        logger.debug("are event lists equal: " + isEventListEqual);

        for (Map.Entry<String, LabelUpdate> entry : labelIdToUpdate.entrySet()) {
            //System.out.println(entry.getKey() + "/" + entry.getValue());

            LabelUpdate lup = entry.getValue();

            logger.debug("is labelupdate a new instance: " + lup.isNew());

            boolean isUpdateRequired = !isEventListEqual || lup.isNew();

            logger.debug("is update required: " + isUpdateRequired);

            if (isUpdateRequired) {
                LabelInfo li = lup.getLabel();
                logger.info("updating label " + li.getLabelId() + " to: " + events);
                lup.setOld();
                String response = service.getClient().postRoomSchedule(li.getLabelId(), roomName, events, service.getUseAlias(), service.getTemplate());
                logger.debug("Response: " + response);
            } else {
                logger.debug("Label " + lup.getLabel().getLabelId() + " is up to date");
            }
        }

        this.events = new ArrayList<Event>(events);
        return true;
    }

    private boolean isEventListEqual(List<Event> previous, List<Event> current) {

        logger.debug("Comparing event lists. Previous: " + previous + " | Current: " + current);

        boolean xor = previous == null ^ current == null;
        if (xor) {
            logger.debug("xor is true");
            return false;
        }

        if (previous.size() != current.size()) {
            logger.debug("sizes differ");
            return false;
        }

        for (int i = 0; i < previous.size(); i++) {
            Event p = previous.get(i);
            Event c = current.get(i);
            if (!p.equals(c)) {
                logger.debug("event difference between:" + p + " and " + c);
                return false;
            }
        }

        return true;
    }

    public List<Event> cloneEvents(List<Event> events)
    {
        List<Event> result = new ArrayList<Event>();
        for(Event e :events){
            result.add(e.clone());
        }
        return result;
    }

}
