/*
 * 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.sling.event.impl.support;

import java.io.Serializable;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.sling.event.jobs.ScheduleInfo;
import org.quartz.CronExpression;

public class ScheduleInfoImpl implements ScheduleInfo, Serializable {

    private static final long serialVersionUID = 1L;

    /** Serialization version. */
    private static final String VERSION = "1";

    public static ScheduleInfoImpl HOURLY(final int minutes) {
        return new ScheduleInfoImpl(ScheduleType.HOURLY, -1, -1, minutes, null, -1, null);
    }

    public static ScheduleInfoImpl CRON(final String expr) {
        return new ScheduleInfoImpl(ScheduleType.CRON, -1, -1, -1, null, -1, expr);
    }

    public static ScheduleInfoImpl AT(final Date at) {
        return new ScheduleInfoImpl(ScheduleType.DATE, -1, -1, -1, at, -1, null);
    }

    public static ScheduleInfoImpl YEARLY(final int month, final int day, final int hour, final int minute) {
        return new ScheduleInfoImpl(ScheduleType.YEARLY, day, hour, minute, null, month, null);
    }

    public static ScheduleInfoImpl MONTHLY(final int day, final int hour, final int minute) {
        return new ScheduleInfoImpl(ScheduleType.MONTHLY, day, hour, minute, null, -1, null);
    }

    public static ScheduleInfoImpl WEEKLY(final int day, final int hour, final int minute) {
        return new ScheduleInfoImpl(ScheduleType.WEEKLY, day, hour, minute, null, -1, null);
    }

    public static ScheduleInfoImpl DAILY(final int hour, final int minute) {
        return new ScheduleInfoImpl(ScheduleType.DAILY, -1, hour, minute, null, -1, null);
    }

    private final ScheduleType scheduleType;

    private final int dayOfWeek;

    private final int hourOfDay;

    private final int minuteOfHour;

    private final Date at;

    private final int monthOfYear;

    private final String expression;

    private ScheduleInfoImpl(final ScheduleType scheduleType,
            final int dayOfWeek,
            final int hourOfDay,
            final int minuteOfHour,
            final Date at,
            final int monthOfYear,
            final String expression) {
        this.scheduleType = scheduleType;
        this.dayOfWeek = dayOfWeek;
        this.hourOfDay = hourOfDay;
        this.minuteOfHour = minuteOfHour;
        this.at = at;
        this.monthOfYear = monthOfYear;
        this.expression = expression;
    }

    public static ScheduleInfoImpl deserialize(final ScheduleType scheduleType, final String s) {
        final String[] parts = s.split("|");
        if ( scheduleType == ScheduleType.YEARLY && parts.length == 4 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        Integer.parseInt(parts[0]),
                        Integer.parseInt(parts[1]),
                        Integer.parseInt(parts[2]),
                        null,
                        Integer.parseInt(parts[3]),
                        null);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        } else if ( scheduleType == ScheduleType.MONTHLY && parts.length == 3 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        Integer.parseInt(parts[0]),
                        Integer.parseInt(parts[1]),
                        Integer.parseInt(parts[2]),
                        null,
                        -1,
                        null);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        } else if ( scheduleType == ScheduleType.WEEKLY && parts.length == 3 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        Integer.parseInt(parts[0]),
                        Integer.parseInt(parts[1]),
                        Integer.parseInt(parts[2]),
                        null,
                        -1,
                        null);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        } else if ( scheduleType == ScheduleType.DAILY && parts.length == 2 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        -1,
                        Integer.parseInt(parts[0]),
                        Integer.parseInt(parts[1]),
                        null,
                        -1,
                        null);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        } else if ( scheduleType == ScheduleType.HOURLY && parts.length == 1 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        -1,
                        -1,
                        Integer.parseInt(parts[0]),
                        null,
                        -1,
                        null);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        } else if ( scheduleType == ScheduleType.CRON && parts.length == 1 ) {
            try {
                return new ScheduleInfoImpl(scheduleType,
                        -1,
                        -1,
                        -1,
                        null,
                        -1,
                        parts[0]);
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        }

        return null;
    }

    public static ScheduleInfoImpl deserialize(final String s) {
        final String[] parts = s.split("\\|");
        if ( parts.length == 8 && parts[0].equals(VERSION) ) {
            try {
                return new ScheduleInfoImpl(ScheduleType.valueOf(parts[1]),
                        Integer.parseInt(parts[2]),
                        Integer.parseInt(parts[3]),
                        Integer.parseInt(parts[4]),
                        (parts[5].equals("null") ? null : new Date(Long.parseLong(parts[5]))),
                        Integer.parseInt(parts[6]),
                        (parts[7].equals("null") ? null : parts[7])
                        );
            } catch ( final IllegalArgumentException iae) {
                // ignore and return null
            }
        }
        return null;
    }

    public String getSerializedString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(VERSION);
        sb.append("|");
        sb.append(this.scheduleType.name());
        sb.append("|");
        sb.append(String.valueOf(this.dayOfWeek));
        sb.append("|");
        sb.append(String.valueOf(this.hourOfDay));
        sb.append("|");
        sb.append(String.valueOf(this.minuteOfHour));
        sb.append("|");
        if ( at == null ) {
            sb.append("null");
        } else {
            sb.append(String.valueOf(at.getTime()));
        }
        sb.append("|");
        sb.append(String.valueOf(this.monthOfYear));
        sb.append("|");
        if ( expression == null ) {
            sb.append("null");
        } else {
            sb.append(String.valueOf(expression));
        }
        return sb.toString();
    }

    @Override
    public ScheduleType getType() {
        return this.scheduleType;
    }

    @Override
    public Date getAt() {
        return this.at;
    }

    @Override
    public int getDayOfWeek() {
        return (this.scheduleType == ScheduleType.WEEKLY ? this.dayOfWeek : -1);
    }

    @Override
    public int getHourOfDay() {
        return this.hourOfDay;
    }

    @Override
    public int getMinuteOfHour() {
        return this.minuteOfHour;
    }

    @Override
    public String getExpression() {
        return this.expression;
    }

    @Override
    public int getMonthOfYear() {
        return this.monthOfYear;
    }

    @Override
    public int getDayOfMonth() {
        return (this.scheduleType == ScheduleType.MONTHLY
                || this.scheduleType == ScheduleType.YEARLY ? this.dayOfWeek : -1);
    }

    public void check(final List<String> errors) {
        switch ( this.scheduleType ) {
        case DAILY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
                         errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
                     }
                     break;
        case DATE :  if ( at == null || at.getTime() <= System.currentTimeMillis() + 2000 ) {
                         errors.add("Date must be in the future : " + at);
                     }
                     break;
        case HOURLY : if ( minuteOfHour < 0 || minuteOfHour > 59 ) {
                          errors.add("Minute must be between 0 and 59 : " + minuteOfHour);
                      }
                      break;
        case WEEKLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
                          errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
                      }
                      if ( dayOfWeek < 1 || dayOfWeek > 7 ) {
                          errors.add("Day must be between 1 and 7 : " + dayOfWeek);
                      }
                      break;
        case MONTHLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
                           errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
                       }
                       if ( dayOfWeek < 1 || dayOfWeek > 28 ) {
                           errors.add("Day must be between 1 and 28 : " + dayOfWeek);
                       }
                       break;
        case YEARLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
                          errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
                      }
                      if ( dayOfWeek < 1 || dayOfWeek > 28 ) {
                          errors.add("Day must be between 1 and 28 : " + dayOfWeek);
                      }
                      if ( monthOfYear < 1 || monthOfYear > 12 ) {
                          errors.add("Month must be between 1 and 12 : " + dayOfWeek);
                      }
                      break;
        case CRON : if ( expression == null ) {
                         errors.add("Expression must be specified.");
                    }
                    try {
                        new CronExpression(this.expression);
                    } catch (final ParseException e) {
                        errors.add("Expression must be valid: " + this.expression);
                    }
        }
    }

    public Date getNextScheduledExecution() {
        final Calendar now = Calendar.getInstance();
        switch ( this.scheduleType ) {
            case DATE : return this.at;
            case DAILY : final Calendar next = Calendar.getInstance();
                         next.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
                         next.set(Calendar.MINUTE, this.minuteOfHour);
                         if ( next.before(now) ) {
                             next.add(Calendar.DAY_OF_WEEK, 1);
                         }
                         return next.getTime();
            case WEEKLY : final Calendar nextW = Calendar.getInstance();
                          nextW.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
                          nextW.set(Calendar.MINUTE, this.minuteOfHour);
                          nextW.set(Calendar.DAY_OF_WEEK, this.dayOfWeek);
                          if ( nextW.before(now) ) {
                              nextW.add(Calendar.WEEK_OF_YEAR, 1);
                          }
                          return nextW.getTime();
            case HOURLY : final Calendar nextH = Calendar.getInstance();
                          nextH.set(Calendar.MINUTE, this.minuteOfHour);
                          if ( nextH.before(now) ) {
                              nextH.add(Calendar.HOUR_OF_DAY, 1);
                          }
                          return nextH.getTime();
            case MONTHLY : final Calendar nextM = Calendar.getInstance();
                           nextM.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
                           nextM.set(Calendar.MINUTE, this.minuteOfHour);
                           nextM.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
                           if ( nextM.before(now) ) {
                               nextM.add(Calendar.MONTH, 1);
                           }
                           return nextM.getTime();
            case YEARLY : final Calendar nextY = Calendar.getInstance();
                          nextY.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
                          nextY.set(Calendar.MINUTE, this.minuteOfHour);
                          nextY.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
                          nextY.set(Calendar.MONTH, this.monthOfYear - 1);
                          if ( nextY.before(now) ) {
                              nextY.add(Calendar.YEAR, 1);
                          }
                          return nextY.getTime();
            case CRON : try {
                            final CronExpression exp = new CronExpression(this.expression);
                            return exp.getNextValidTimeAfter(new Date());
                        } catch (final ParseException e) {
                            // as we check the expression in check() everything should be fine here
                        }
        }
        return null;
    }

    /**
     * If the job is scheduled daily or weekly, return the cron expression
     */
    public String getCronExpression() {
        if ( this.scheduleType == ScheduleType.DAILY ) {
            final StringBuilder sb = new StringBuilder("0 ");
            sb.append(String.valueOf(this.minuteOfHour));
            sb.append(' ');
            sb.append(String.valueOf(this.hourOfDay));
            sb.append(" * * ?");
            return sb.toString();
        } else if ( this.scheduleType == ScheduleType.WEEKLY ) {
            final StringBuilder sb = new StringBuilder("0 ");
            sb.append(String.valueOf(this.minuteOfHour));
            sb.append(' ');
            sb.append(String.valueOf(this.hourOfDay));
            sb.append(" ? * ");
            sb.append(String.valueOf(this.dayOfWeek));
            return sb.toString();
        } else if ( this.scheduleType == ScheduleType.HOURLY ) {
            final StringBuilder sb = new StringBuilder("0 ");
            sb.append(String.valueOf(this.minuteOfHour));
            sb.append(" * * * ?");
            return sb.toString();
        } else if ( this.scheduleType == ScheduleType.MONTHLY ) {
            final StringBuilder sb = new StringBuilder("0 ");
            sb.append(String.valueOf(this.minuteOfHour));
            sb.append(' ');
            sb.append(String.valueOf(this.hourOfDay));
            sb.append(' ');
            sb.append(String.valueOf(this.dayOfWeek));
            sb.append(" * ?");
            return sb.toString();
        } else if ( this.scheduleType == ScheduleType.YEARLY ) {
            final StringBuilder sb = new StringBuilder("0 ");
            sb.append(String.valueOf(this.minuteOfHour));
            sb.append(' ');
            sb.append(String.valueOf(this.hourOfDay));
            sb.append(' ');
            sb.append(String.valueOf(this.dayOfWeek));
            sb.append(' ');
            sb.append(String.valueOf(this.monthOfYear - 1));
            sb.append(" ?");
            return sb.toString();
        } else if ( this.scheduleType == ScheduleType.CRON ) {
            return this.expression;
        }
        return null;
    }

    @Override
    public String toString() {
        return "ScheduleInfo [scheduleType=" + scheduleType
                + ", dayOfWeek=" + dayOfWeek + ", hourOfDay=" + hourOfDay
                + ", minuteOfHour=" + minuteOfHour + ", at=" + at
                + ", monthOfYear=" + monthOfYear + ", expression=" + expression
                + "]";
    }
}
