package com.ximai.mes.pro.schedule;

import java.util.*;
import java.util.stream.Collectors;

public class CalendarManager {

    private Map<Resource, List<Calendar.OccupiedCalendar>> occupiedCalendar = new HashMap<Resource, List<Calendar.OccupiedCalendar>>();
    private Map<Resource, List<Calendar.LeisureCalendar>> leisureCalendar = new  HashMap<Resource, List<Calendar.LeisureCalendar>>();
    private Map<Task, List<Calendar.OccupiedCalendar>> taskOccupiedCalendar = new  HashMap<Task, List<Calendar.OccupiedCalendar>>();

    public void addWorkingCalendar(Calendar.WorkingCalendar calendar)
    {
        Calendar.LeisureCalendar leisureCalendarItem = new Calendar.LeisureCalendar() {{
            setStartedTime(calendar.getStartedTime());
            setEndedTime(calendar.getEndedTime());
            setResource(calendar.getResource());
            setShiftType(calendar.getShiftType());
            setStartedTime2(calendar.getStartedTime2());
            setEndedTime2(calendar.getEndedTime2());
        }};
        leisureCalendarItem.calendarData.putAll(calendar.calendarData);
        getLeisureCalendar(calendar.getResource()).add(leisureCalendarItem);
    }

    /**
     * 添加时间占用
     * @param calendar
     */
    public void addOccupiedCalendar(Calendar.OccupiedCalendar calendar) {
        getOccupiedCalendar(calendar.getResource()).add(calendar);
        getOccupiedCalendar(calendar.getTask()).add(calendar);
        List<Calendar.LeisureCalendar> leisureCalendar = getLeisureCalendar(calendar.getResource());

        if (calendar.getResource().getIsParallel())
        {
            leisureCalendar.forEach(s->{
                s.calendarData.putAll(calendar.calendarData);
            });
            return;
        }
        //查询占用时间覆盖全部空闲时间段
        List<Calendar> fullOccupiedItems = leisureCalendar.stream().filter(s->
                s.getStartedTime().getSeconds()>=calendar.getStartedTime().getSeconds() &&
                        s.getEndedTime().getSeconds()<=calendar.getEndedTime().getSeconds()).collect(Collectors.toList());

        fullOccupiedItems.forEach(item ->{
            leisureCalendar.remove(item);
            calendar.calendarData.putAll(item.calendarData);
        });

        List<Calendar> leftOccupiedItems = leisureCalendar.stream().filter(s->
                calendar.getStartedTime().getSeconds()<=s.getStartedTime().getSeconds() &&
                        calendar.getEndedTime().getSeconds()>s.getStartedTime().getSeconds() &&
                        calendar.getEndedTime().getSeconds()<s.getEndedTime().getSeconds()).collect(Collectors.toList());

        leftOccupiedItems.forEach(item ->{
            item.setStartedTime(calendar.getEndedTime());
            calendar.calendarData.putAll(item.calendarData);
        });

        List<Calendar> rightOccupiedItems = leisureCalendar.stream().filter(s->
                calendar.getStartedTime().getSeconds()>s.getStartedTime().getSeconds() &&
                        calendar.getStartedTime().getSeconds()<s.getEndedTime().getSeconds() &&
                        calendar.getEndedTime().getSeconds()>=s.getEndedTime().getSeconds()).collect(Collectors.toList());

        rightOccupiedItems.forEach(item ->{
            item.setEndedTime(calendar.getStartedTime());
            calendar.calendarData.putAll(item.calendarData);
        });

        List<Calendar> centerOccupiedItems = leisureCalendar.stream().filter(s->
                s.getStartedTime().getSeconds() < calendar.getStartedTime().getSeconds() &&
                        s.getEndedTime().getSeconds()>calendar.getEndedTime().getSeconds()).collect(Collectors.toList());

        centerOccupiedItems.forEach(item -> {
            leisureCalendar.remove(item);
            Calendar.LeisureCalendar left = new Calendar.LeisureCalendar(){{
                this.setResource(calendar.getResource());
                this.setStartedTime(item.getStartedTime());
                this.setEndedTime(calendar.getStartedTime());
                this.setStartedTime2(item.getStartedTime2());
                this.setEndedTime2(calendar.getEndedTime2());
            }};
            left.calendarData.putAll(item.calendarData);
            leisureCalendar.add(left);
            Calendar.LeisureCalendar right = new Calendar.LeisureCalendar() {{
                this.setResource(calendar.getResource());
                this.setStartedTime(calendar.getEndedTime());
                this.setEndedTime(item.getEndedTime());
                this.setStartedTime2(calendar.getEndedTime2());
                this.setEndedTime2(item.getEndedTime2());
            }};
            right.calendarData.putAll(item.calendarData);
            leisureCalendar.add(right);
            calendar.calendarData.putAll(item.calendarData);
        });

        if(!centerOccupiedItems.isEmpty()){
            leisureCalendar.sort(Comparator.comparing(Calendar.LeisureCalendar::getStartedTime));
        }
    }

    public List<Calendar> getCalendar(Resource resource)
    {
        List<Calendar> rst = new ArrayList<Calendar>();
        rst.addAll(this.getLeisureCalendar(resource));
        rst.addAll(this.getOccupiedCalendar(resource));
        return rst;
    }

    public List<Calendar.OccupiedCalendar> getOccupiedCalendar(Resource resource)
    {
        if(!occupiedCalendar.containsKey(resource)){
            occupiedCalendar.put(resource, new ArrayList<Calendar.OccupiedCalendar>());
        }
        return occupiedCalendar.get(resource);
    }

    public List<Calendar.LeisureCalendar> getLeisureCalendar(Resource resource)
    {
        if(!leisureCalendar.containsKey(resource)){
            leisureCalendar.put(resource, new ArrayList<Calendar.LeisureCalendar>());
        }
        return leisureCalendar.get(resource);
    }

    public List<Calendar.OccupiedCalendar> getOccupiedCalendar(Task task)
    {
        if(!taskOccupiedCalendar.containsKey(task)){
            taskOccupiedCalendar.put(task, new ArrayList<Calendar.OccupiedCalendar>());
        }
        return taskOccupiedCalendar.get(task);
    }
}
