/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.1 (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.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.faces.facelets.component.schedule;

import com.icesoft.faces.facelets.component.names.BeanNames;
import com.icesoft.faces.facelets.component.names.ParameterNames;
import com.icesoft.faces.facelets.component.schedule.common.CalendarViewModel;
import com.icesoft.faces.facelets.component.schedule.day.DayViewController;
import com.icesoft.faces.facelets.component.schedule.month.MonthViewController;
import com.icesoft.faces.facelets.component.schedule.week.WeekViewController;
import com.icesoft.faces.facelets.component.schedule.year.YearViewController;
import com.icesoft.faces.facelets.component.util.CalendarViewUtil;
import com.icesoft.faces.facelets.component.util.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import java.io.Serializable;
import java.util.Calendar;

/**
 * Calendar controller is responsible for chaining the model state when a
 * users clicks on the UI tabs that represent the day, week, month and year
 * states.
 */
public class CalendarController implements Serializable {

    protected final Log logger =
            LogFactory.getLog(CalendarController.class);

    // singleton calendar service
    protected CalendarViewService calendarViewService;

    private AbstractCalendarViewController currentCalViewController = new DayViewController();

    private boolean calendar24Hour = false;

    /**
     * Changes calendar view from day, month, week via the command
     * buttons at the top.
     * <p/>
     * contextParam 'calendarViewType' using class constants.
     *
     * @param event jsf event that we get context param form for which
     *              view controller to construct
     */
    public void changeCalendarView(ActionEvent event) {

        // get the context param for the view name
        String calendarViewType = Util.getRequestParameter(
                ParameterNames.CALENDAR_VIEW_TYPE);

        // check if have an instance.
        if (currentCalViewController != null) {
            // check to see if the requested one is the same as the current, if
            // so we do nothing
            if (currentCalViewController.getViewModel().getViewName()
                    .equals(calendarViewType)) {
                return;
            } // if the request isn't the current then dispose of it.
            else {
                currentCalViewController.dispose();
            }

            // create a new instance of the requested calendar type
            currentCalViewController = getInstance(calendarViewType);
            logger.info("Changed calendar view: " + calendarViewType);

            // check for an update to the cursor
            if (Util.getRequestParameter(
                    ParameterNames.DAY_DATE_CURSOR) != null) {
                if (Util.getRequestParameter(
                        ParameterNames.DAY_DATE_CURSOR).length() > 0) {
                    int day = Integer.parseInt(Util.getRequestParameter(
                            ParameterNames.DAY_DATE_CURSOR));
                    int month = Integer.parseInt(Util.getRequestParameter(
                            ParameterNames.MONTH_DATE_CURSOR));
                    int year = Integer.parseInt(Util.getRequestParameter(
                            ParameterNames.YEAR_DATE_CURSOR));
                    CalendarViewUtil cvu = (CalendarViewUtil) Util.getManagedBean(BeanNames.CALENDAR_VIEW_UTIL);
                    Calendar newDateCursor = cvu.getLocalizedCalendar();
                    newDateCursor.set(year, month, day);
                    currentCalViewController.getViewModel().setDateCursor(newDateCursor);
                    logger.info("setting date cursor: " + year + " " + month + " " + day);
                }
            }

            // initialized the data model, after view moved the cursor
            currentCalViewController.setInitializeDataModel(calendarViewService);
        }
    }

    public void setCalendarViewService(CalendarViewService calendarViewService) {
        this.calendarViewService = calendarViewService;
        // Initialize data model
        currentCalViewController.setInitializeDataModel(this.calendarViewService);
    }

    /**
     * Controller factory for given view types.
     *
     * @param viewType view type form type defined in @link{CalendarViewBean}
     * @return respective calendar view controller, if none can be created null
     *         is returned.
     */
    private AbstractCalendarViewController getInstance(final String viewType) {
        if (CalendarViewModel.DAY_VIEW.equals(viewType)) {
            return new DayViewController();
        } else if (CalendarViewModel.WEEK_VIEW.equals(viewType)) {
            return new WeekViewController();
        } else if (CalendarViewModel.MONTH_VIEW.equals(viewType)) {
            return new MonthViewController();
        } else if (CalendarViewModel.YEAR_VIEW.equals(viewType)) {
            return new YearViewController();
        } else {
            return null;
        }
    }

    public void viewableHoursValueChangeListener(ValueChangeEvent e) {
        CalendarViewUtil cvu = (CalendarViewUtil) Util.getManagedBean(BeanNames.CALENDAR_VIEW_UTIL);
        if ((Boolean) e.getNewValue()) {
            cvu.setHoursInDay(CalendarViewUtil.ALL_DAY_HOURS_IN_DAY);
            cvu.setStartHour(CalendarViewUtil.ALL_DAY_START_HOUR);
        } else {
            cvu.setHoursInDay(CalendarViewUtil.DEFAULT_HOURS_IN_DAY);
            cvu.setStartHour(CalendarViewUtil.DEFAULT_START_HOUR);
        }

        // Re-initialize now that we have changed the viewable hours
        currentCalViewController.setInitializeDataModel(calendarViewService);
    }

    public boolean isCalendar24Hour() {
        return calendar24Hour;
    }

    public void setCalendar24Hour(boolean calendar24Hour) {
        this.calendar24Hour = calendar24Hour;
    }

    public AbstractCalendarViewController getCurrentCalViewController() {
        return currentCalViewController;
    }

    public void setCurrentCalViewController(AbstractCalendarViewController currentCalViewController) {
        this.currentCalViewController = currentCalViewController;
    }

}
