/*
 * 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.select;

import javax.faces.event.PhaseId;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * <p>Backing bean that should be used with the SelectInputTime component.
 * The intended use is to only use the bean with SelectInputTime and ideally
 * only manipulate the SelectInputCalendar calendar instance variable.  If the
 * api you are interacting with uses Date object then it can be easily be
 * changed to a GregorianCalendar object with the method setTime().
 * For example:</p>
 * <ul>someSelectInputCalendar.setDate(myDate);</ul>
 *
 * @author ICEfaces Technologies Inc.
 */
public class SelectInputTime extends SelectInputCalendar {

    private int hour = 0;
    private int minute = 0;

    private static SelectItem[] hours;
    private static SelectItem[] minutes;

    static {
        // hours and minutes never change so they can also be final
        hours = new SelectItem[24];
        for (int i = 0; i < 24; i++) {
            hours[i] = new SelectItem(i, i + "h");
        }
        minutes = new SelectItem[60];
        for (int i = 0; i < 60; i++) {
            if (i >= 10) {
                minutes[i] = new SelectItem(i, i + "m");
            } else {
                minutes[i] = new SelectItem(i, "0" + i + "m");
            }
        }
    }

    /**
     * Creates a new SelectInputCalendar object.  This method will automatically
     * sync the calendar with the current date.
     *
     * @param timezone timezone that the calendar resides in.
     */
    public SelectInputTime(TimeZone timezone) {

        if (timezone != null) {
            calendar = new GregorianCalendar(timezone);
        } else {
            calendar = new GregorianCalendar(TimeZone.getDefault());
        }
        calendar.set(Calendar.MILLISECOND, 0);

        setDefaultMaxDays();
        // update values of year, month day
        updateCalendarValues();
        setMaxYears();
    }

    /**
     * Creates a new SelectInputCalendar object.  This method will automatically
     * sync the calendar with the current date. The server's current timezone is
     * used for this instance.
     */
    public SelectInputTime() {
        this(null);
    }


    /**
     * When the hour dropdown is changed we'll want to update the backing
     * values (GregorianCalendar, bean value)
     *
     * @param event of the change
     */
    public void hourChanged(ValueChangeEvent event) {
        if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
            event.setPhaseId(PhaseId.INVOKE_APPLICATION);
            event.queue();
        } else {
            int newHour = (Integer) event.getNewValue();
            calendar.set(Calendar.HOUR_OF_DAY, newHour);

            updateCalendarValues();
        }
    }

    /**
     * When the minute dropdown is changed we'll want to update the backing
     * values (GregorianCalendar, bean value)
     *
     * @param event of the change
     */
    public void minuteChanged(ValueChangeEvent event) {
        if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
            event.setPhaseId(PhaseId.INVOKE_APPLICATION);
            event.queue();
        } else {
            int newMinute = (Integer) event.getNewValue();
            calendar.set(Calendar.MINUTE, newMinute);

            updateCalendarValues();
        }
    }

    /**
     * Gets the timezone used by the GregorianCalendar instance as a readable
     * string such as PST or GMT
     *
     * @return timezone from the GregorianCalendar as a string
     */
    public String getTimeZoneAsString() {
        TimeZone tz = calendar.getTimeZone();

        if (tz != null) {
            return tz.getDisplayName(false, TimeZone.SHORT);
        }

        return null;
    }

    /**
     * Converts the calendar values into three primary values, year, month and
     * day, represented by ints.
     */
    protected void updateCalendarValues() {

        super.updateCalendarValues();

        hour = calendar.get(Calendar.HOUR_OF_DAY);
        minute = calendar.get(Calendar.MINUTE);
    }


    public GregorianCalendar getCalendar() {
        return calendar;
    }

    public void setCalendar(GregorianCalendar calendar) {
        this.calendar = calendar;
    }

    public SelectItem[] getHours() {
        return hours;
    }

    public SelectItem[] getMinutes() {
        return minutes;
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public int getMinute() {
        return minute;
    }

    public void setMinute(int minute) {
        this.minute = minute;
    }
}