/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/

package org.apache.ofbiz.workeffort.workeffort;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import net.fortuna.ical4j.model.*;
import net.fortuna.ical4j.model.property.*;

import org.apache.ofbiz.service.calendar.TemporalExpression;
import org.apache.ofbiz.service.calendar.TemporalExpressionVisitor;
import org.apache.ofbiz.service.calendar.TemporalExpressions;
import org.apache.ofbiz.service.calendar.TemporalExpressions.*;

import com.ibm.icu.util.Calendar;

/** Temporal Expression to iCalendar recurrence converter. The conversion results
 * (or conversion success) are unpredictable since the OFBiz Temporal Expressions
 * are more sophisticated than iCalendar recurrences. This class attempts to
 * make a best attempt at conversion and throws <code>IllegalStateException</code>
 * when conversion is not possible.
 */
public class ICalRecurConverter implements TemporalExpressionVisitor {
    protected static final WeekDay dayOfWeekArray[] = {WeekDay.SU, WeekDay.MO, WeekDay.TU, WeekDay.WE, WeekDay.TH, WeekDay.FR, WeekDay.SA};

    @SuppressWarnings("unchecked")
    public static void convert(TemporalExpression expr, PropertyList eventProps) {
        ICalRecurConverter converter = new ICalRecurConverter();
        expr.accept(converter);
        DtStart dateStart = (DtStart) eventProps.getProperty(Property.DTSTART);
        if (converter.dateStart != null) {
            if (dateStart != null) {
                eventProps.remove(dateStart);
            }
            dateStart = converter.dateStart;
            eventProps.add(dateStart);
        }
        if (dateStart != null && converter.exRuleList.size() > 0) {
            // iCalendar quirk - if exclusions exist, then the start date must be excluded also
            ExDate exdate = new ExDate();
            exdate.getDates().add(dateStart.getDate());
            converter.exDateList.add(exdate);
        }
        eventProps.addAll(converter.incDateList);
        eventProps.addAll(converter.incRuleList);
        eventProps.addAll(converter.exDateList);
        eventProps.addAll(converter.exRuleList);
    }

    protected DtStart dateStart = null;
    protected List<DateListProperty> incDateList = new LinkedList<DateListProperty>();
    protected List<DateListProperty> exDateList = new LinkedList<DateListProperty>();
    protected List<RRule> incRuleList = new LinkedList<RRule>();
    protected List<ExRule> exRuleList = new LinkedList<ExRule>();
    protected VisitorState state = new VisitorState();
    protected Stack<VisitorState> stateStack = new Stack<VisitorState>();

    protected ICalRecurConverter() {}

    @SuppressWarnings("unchecked")
    protected Recur consolidateRecurs(List<Recur> recurList) {
        // Try to consolidate a list of Recur instances into one instance
        Set<Integer> monthList = new HashSet<Integer>();
        Set<Integer> monthDayList = new HashSet<Integer>();
        Set<WeekDay> weekDayList = new HashSet<WeekDay>();
        Set<Integer> hourList = new HashSet<Integer>();
        Set<Integer> minuteList = new HashSet<Integer>();
        String freq = null;
        int freqCount = 0;
        for (Recur recur : recurList) {
            monthList.addAll(recur.getMonthList());
            monthDayList.addAll(recur.getMonthDayList());
            weekDayList.addAll(recur.getDayList());
            hourList.addAll(recur.getHourList());
            minuteList.addAll(recur.getMinuteList());
            if (recur.getInterval() != 0) {
                freq = recur.getFrequency();
                freqCount = recur.getInterval();
            }
        }
        if (freq == null && monthList.size() > 0) {
            freq = Recur.MONTHLY;
        } else if (freq == null && (monthDayList.size() > 0 || weekDayList.size() > 0)) {
            freq = Recur.DAILY;
        } else if (freq == null && hourList.size() > 0) {
            freq = Recur.HOURLY;
        } else if (freq == null && minuteList.size() > 0) {
            freq = Recur.MINUTELY;
        }
        if (freq == null) {
            throw new IllegalStateException("Unable to convert intersection");
        }
        Recur newRecur = new Recur(freq, 0);
        if (freqCount != 0) {
            newRecur.setInterval(freqCount);
        }
        newRecur.getMonthList().addAll(monthList);
        newRecur.getMonthDayList().addAll(monthDayList);
        newRecur.getDayList().addAll(weekDayList);
        newRecur.getHourList().addAll(hourList);
        newRecur.getMinuteList().addAll(minuteList);
        return newRecur;
    }

    // ----- TemporalExpressionVisitor Implementation ----- //

    @Override
    public void visit(Difference expr) {
        VisitorState newState = new VisitorState();
        newState.isIntersection = this.state.isIntersection;
        this.stateStack.push(this.state);
        this.state = newState;
        expr.getIncluded().accept(this);
        newState.isExcluded = true;
        expr.getExcluded().accept(this);
        this.state = this.stateStack.pop();
        if (this.state.isIntersection) {
            this.state.inclRecurList.addAll(newState.inclRecurList);
            this.state.exRecurList.addAll(newState.exRecurList);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void visit(HourRange expr) {
        NumberList hourList = new NumberList();
        hourList.addAll(expr.getHourRangeAsSet());
        Recur recur = new Recur(Recur.HOURLY, 0);
        recur.getHourList().addAll(hourList);
        this.state.addRecur(recur);
    }

    @Override
    public void visit(Intersection expr) {
        this.stateStack.push(this.state);
        VisitorState newState = new VisitorState();
        newState.isExcluded = this.state.isExcluded;
        newState.isIntersection = true;
        this.state = newState;
        for (TemporalExpression childExpr : expr.getExpressionSet()) {
            childExpr.accept(this);
        }
        this.state = this.stateStack.pop();
        if (newState.inclRecurList.size() > 0) {
            this.incRuleList.add(new RRule(this.consolidateRecurs(newState.inclRecurList)));
        }
        if (newState.exRecurList.size() > 0) {
            this.exRuleList.add(new ExRule(this.consolidateRecurs(newState.exRecurList)));
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void visit(MinuteRange expr) {
        NumberList minuteList = new NumberList();
        minuteList.addAll(expr.getMinuteRangeAsSet());
        Recur recur = new Recur(Recur.MINUTELY, 0);
        recur.getMinuteList().addAll(minuteList);
        this.state.addRecur(recur);
    }

    @Override
    public void visit(Null expr) {}

    @Override
    public void visit(Substitution expr) {
        // iCalendar format does not support substitutions. Do nothing for now.
    }

    @Override
    public void visit(TemporalExpressions.DateRange expr) {
        if (this.state.isExcluded) {
            throw new IllegalStateException("iCalendar does not support excluded date ranges");
        }
        org.apache.ofbiz.base.util.DateRange range = expr.getDateRange();
        PeriodList periodList = new PeriodList();
        periodList.add(new Period(new DateTime(range.start()), new DateTime(range.end())));
        this.incDateList.add(new RDate(periodList));
    }

    @Override
    public void visit(TemporalExpressions.DayInMonth expr) {
        Recur recur = new Recur(Recur.MONTHLY, 0);
        recur.getDayList().add(new WeekDay(dayOfWeekArray[expr.getDayOfWeek() - 1], expr.getOccurrence()));
        this.state.addRecur(recur);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void visit(TemporalExpressions.DayOfMonthRange expr) {
        int startDay = expr.getStartDay();
        int endDay = expr.getEndDay();
        NumberList dayList = new NumberList();
        dayList.add(startDay);
        while (startDay != endDay) {
            startDay++;
            dayList.add(startDay);
        }
        Recur recur = new Recur(Recur.DAILY, 0);
        recur.getMonthDayList().addAll(dayList);
        this.state.addRecur(recur);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void visit(TemporalExpressions.DayOfWeekRange expr) {
        int startDay = expr.getStartDay();
        int endDay = expr.getEndDay();
        WeekDayList dayList = new WeekDayList();
        dayList.add(dayOfWeekArray[startDay - 1]);
        while (startDay != endDay) {
            startDay++;
            if (startDay > Calendar.SATURDAY) {
                startDay = Calendar.SUNDAY;
            }
            dayList.add(dayOfWeekArray[startDay - 1]);
        }
        Recur recur = new Recur(Recur.DAILY, 0);
        recur.getDayList().addAll(dayList);
        this.state.addRecur(recur);
    }

    @Override
    public void visit(TemporalExpressions.Frequency expr) {
        if (this.dateStart == null) {
            this.dateStart = new DtStart(new net.fortuna.ical4j.model.Date(expr.getStartDate()));
        }
        int freqCount = expr.getFreqCount();
        int freqType = expr.getFreqType();
        switch (freqType) {
        case Calendar.SECOND:
            this.state.addRecur((new Recur(Recur.SECONDLY, freqCount)));
            break;
        case Calendar.MINUTE:
            this.state.addRecur((new Recur(Recur.MINUTELY, freqCount)));
            break;
        case Calendar.HOUR:
            this.state.addRecur((new Recur(Recur.HOURLY, freqCount)));
            break;
        case Calendar.DAY_OF_MONTH:
            this.state.addRecur((new Recur(Recur.DAILY, freqCount)));
            break;
        case Calendar.MONTH:
            this.state.addRecur((new Recur(Recur.MONTHLY, freqCount)));
            break;
        case Calendar.YEAR:
            this.state.addRecur((new Recur(Recur.YEARLY, freqCount)));
            break;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void visit(TemporalExpressions.MonthRange expr) {
        int startMonth = expr.getStartMonth();
        int endMonth = expr.getEndMonth();
        Calendar cal = Calendar.getInstance();
        int maxMonth = cal.getActualMaximum(Calendar.MONTH);
        NumberList monthList = new NumberList();
        monthList.add(startMonth + 1);
        while (startMonth != endMonth) {
            startMonth++;
            if (startMonth > maxMonth) {
                startMonth = Calendar.JANUARY;
            }
            monthList.add(startMonth + 1);
        }
        Recur recur = new Recur(Recur.MONTHLY, 0);
        recur.getMonthList().addAll(monthList);
        this.state.addRecur(recur);
    }

    @Override
    public void visit(Union expr) {
        for (TemporalExpression childExpr : expr.getExpressionSet()) {
            childExpr.accept(this);
        }
    }

    protected class VisitorState {
        public boolean isExcluded = false;
        public boolean isIntersection = false;
        public List<Recur> inclRecurList = new LinkedList<Recur>();
        public List<Recur> exRecurList = new LinkedList<Recur>();
        public void addRecur(Recur recur) {
            if (this.isIntersection) {
                if (this.isExcluded) {
                    this.exRecurList.add(recur);
                } else {
                    this.inclRecurList.add(recur);
                }
            } else {
                if (this.isExcluded) {
                    exRuleList.add(new ExRule(recur));
                } else {
                    incRuleList.add(new RRule(recur));
                }
            }
        }
    }
}
