/*
 * Copyright 2009 55 Minutes (http://www.55minutes.com)
 * 
 * Licensed 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 fiftyfive.wicket.datetime;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.model.IModel;


/**
 * This class is based on {@link org.apache.wicket.extensions.yui.calendar.DatePicker},
 * with the added functionality that a minimum and/or maximum date can be
 * specified by the caller.
 */
public class RestrictedDatePicker extends DatePicker
{
    /*
    ** Models representing the start and end date to restrict the date picker
    ** to, and an initial date that determines which month is displayed at
    ** load time.
    */
    private IModel _initialDateModel;
    private IModel _startDateModel;
    private IModel _endDateModel;

    /**
     * RestrictedDatePicker constructor
     */
    public RestrictedDatePicker()
    {
    }

    /**
     * RestrictedDatePicker constructor
     *
     * @param initialDateModel  A model representing the month to show when
     *                          the widget is first loaded.
     * @param startDateModel    A model representing the start date to restrict
     *                          the date picker to.
     * @param endDateModel      A model representing the end date to restrict
     *                          the date picker to.
     */
    public RestrictedDatePicker(IModel initialDateModel, IModel startDateModel, 
                                IModel endDateModel)
    {
        if(startDateModel == null && endDateModel == null)
        {
            throw new IllegalArgumentException("Both startDateModel and " +
                                               "endDateModel cannot be null.");
        }
        
        if(initialDateModel != null)
        {
            _initialDateModel = initialDateModel;
        }
        
        if(startDateModel != null)
        {
            _startDateModel = startDateModel;
        }
        
        if(endDateModel != null)
        {
            _endDateModel = endDateModel;
        }
    }
    
    /**
     * Detaches the various initial, start and end date models
     * that are associated with this picker.
     */
    @Override
    public void detach(Component component)
    {
        super.detach(component);
        if(_initialDateModel != null) _initialDateModel.detach();
        if(_startDateModel != null) _startDateModel.detach();
        if(_endDateModel != null) _endDateModel.detach();
    }

    /**
     * Set the initial date model.
     *
     * @param newInitialDateModel   A model representing the initial date for
     *                              this date picker; the widget will show the
     *                              month specified when loaded.
     */
    public void setInitialDateModel(IModel newInitialDateModel)
    {
        _initialDateModel = newInitialDateModel;
    }

    /**
     * Set the start date model.
     *
     * @param newStartDateModel     A model representing the start date for this
     *                              date picker; the user will be unable to
     *                              select a date prior to this date, if it is
     *                              specified.
     */
    public void setStartDateModel(IModel newStartDateModel)
    {
        _startDateModel = newStartDateModel;
    }

    /**
     * Set the end date model.
     *
     * @param newEndDateModel   A model representing the end date for this date
     *                          picker; the user will be unable to select a
     *                          date following this date, if it is specified.
     *                          
     */
    public void setEndDateModel(IModel newEndDateModel)
    {
        _endDateModel = newEndDateModel;
    }
    
    /**
     * Configure the widget with the start and end dates specified.
     * @param widgetProperties  the current widget properties
     */
    protected void configure(Map widgetProperties)
    {
        super.configure(widgetProperties);
        
        /*
        ** If the initial, start and end date model objects exist, add pagedate,
        ** mindate and maxdate properties to the widget configuration.
        */
        if(_initialDateModel != null)
        {
            Date id = (Date )_initialDateModel.getObject();
            if(id != null)
            {
                widgetProperties.put("pagedate", FORMAT_PAGEDATE.format(id));
            }
        }

        if(_startDateModel != null)
        {
            Date sd = (Date )_startDateModel.getObject();
            if(sd != null)
            {
                widgetProperties.put("mindate", FORMAT_DATE.format(sd));
            }
        }

        if(_endDateModel != null)
        {
            Date ed = (Date )_endDateModel.getObject();
            if(ed != null)
            {
                widgetProperties.put("maxdate", FORMAT_DATE.format(ed));
            }
        }
    }
}

@@ -653,16 +653,51 @@
 time;%0A%0A%0A
+import java.text.SimpleDateFormat;%0A
 import j
@@ -5056,20 +5056,82 @@
 put(
-%22pagedate%22, 
+%0A                    %22pagedate%22,%0A                    new SimpleDateFormat(
 FORM
@@ -5137,24 +5137,25 @@
 MAT_PAGEDATE
+)
 .format(id))
@@ -5153,16 +5153,33 @@
 rmat(id)
+%0A                
 );%0A     
@@ -5384,19 +5384,81 @@
 put(
-%22mindate%22, 
+%0A                    %22mindate%22,%0A                    new SimpleDateFormat(
 FORM
@@ -5456,32 +5456,33 @@
 rmat(FORMAT_DATE
+)
 .format(sd));%0A  
@@ -5476,16 +5476,33 @@
 rmat(sd)
+%0A                
 );%0A     
@@ -5703,19 +5703,81 @@
 put(
-%22maxdate%22, 
+%0A                    %22maxdate%22,%0A                    new SimpleDateFormat(
 FORM
@@ -5783,16 +5783,17 @@
 MAT_DATE
+)
 .format(
@@ -5795,16 +5795,33 @@
 rmat(ed)
+%0A                
 );%0A     

Fix compilation error. The latest `DatePicker` code uses strings instead of `DateFormat` objects, so our code has to be changed to match. Fixes #19.