<?php

/*
* @copyright Copyright (C) 2005-2009 Keyboard Monkeys Ltd. http://www.kb-m.com
* @license http://creativecommons.org/licenses/BSD/ BSD Licensese
* @author Keyboard Monkeys Ltd.
* @since CommunityID0.9
* @package CommunityID
* @packager Keyboard Monkeys
*/

/**
* Based on 
* http://zfsite.andreinikolov.com/2008/05/part-4-zend_form-captcha-password-confirmation-date-selector-field-zend_translate/
*/
class Monkeys_Form_Element_Date extends Zend_Form_Element_Xhtml 
{
    /**
     * Use formSelect view helper by default
     * @var string
     */
    public $helper = 'formDateSelects';    
 
    /**
     * This array will hold options: 
     * showEmpty - bool, if true will show and allow empty date 
     * startYear, endYear - start and end year to show
     * reverseYears - if true - years will be print from most recent backwards
     *  
     * Zend_Form_Decorator_ViewHelper will pass this array as argument to the
     * view helper, responsible for rendering this element  
     * 
     * @var array
     */
    public $options = array();  

    private $_decorator;

    public function __construct($spec, $options = array())
    {
        $options = array_merge($options, array('disableLoadDefaultDecorators' =>true));
        parent::__construct($spec, $options);

        $this->_decorator = new Monkeys_Form_Decorator_Composite();
        $this->addDecorator($this->_decorator);
    }

    public function setDecoratorOptions(array $options)
    {
        $this->_decorator->setOptions($options);

        return $this;
    }
 
    public function init()
    {
        $this->options['showEmpty'] = true;
        $this->options['startYear'] = 1900;        
        $this->options['endYear'] = (int) date("Y");
        $this->options['reverseYears'] = false;
    }
 
    public function setShowEmptyValues($value)
    {
        $this->options['showEmpty'] = (bool) $value;
        return $this;        
    }
 
    public function setStartEndYear($start = null, $end = null)
    {
        if ($start)
        {
            $this->options['startYear'] = (int) $start;            
        }
 
        if ($end)
        {
            $this->options['endYear'] = (int) $end;            
        }
        return $this;        
    }
 
    public function setReverseYears($value)
    {
        $this->options['reverseYears'] = (bool) $value;
        return $this;
    }
 
 
    /**
     * We want to get the date from our auxiliary fields here
     *
     * @param mixed $value 
     * @param mixed $context
     * @return boolean
     */
    public function isValid($value, $context = null)
    {
        $fieldName = $this->getName();
        $auxiliaryFieldsNames = $this->getDayMonthYearFieldNames($fieldName);
        if (isset($context[$auxiliaryFieldsNames['day']]) && isset($context[$auxiliaryFieldsNames['month']]) 
                && isset($context[$auxiliaryFieldsNames['year']]))
        {
            if ($context[$auxiliaryFieldsNames['year']] == '-' 
                || $context[$auxiliaryFieldsNames['month']] == '-' 
                || $context[$auxiliaryFieldsNames['day']] == '-')
            {
                $value = null;
            }
            else
            {
                $value = str_pad($context[$auxiliaryFieldsNames['year']], 4, '0', STR_PAD_LEFT) . '-'
                    . str_pad($context[$auxiliaryFieldsNames['month']], 2, '0', STR_PAD_LEFT) . '-'
                    . str_pad($context[$auxiliaryFieldsNames['day']], 2, '0', STR_PAD_LEFT);
            }
 
            $this->setValue($value);
        }
 
        return parent::isValid($value, $context);
    }
 
    /**
     * Makes day, month and year names from given element name. Special case is array notation.
     *
     * Given a value such as foo[bar][baz], the generated names will be
     * foo[bar][baz_day], foo[bar][baz_month] and foo[bar][baz_year]
     * I know it is bad design to have this function here and in the View Helper, 
     * but I really can't think of other way 
     *
     * @param  string $value
     * @return array
     */
    protected function getDayMonthYearFieldNames($value)
    {
        if (empty($value) || !is_string($value)) {
            return $value;
        }
 
        $ret = array(
                'day' => $value . '_day',
                'month' => $value . '_month',
                'year' => $value . '_year'
                );
 
        if (strstr($value, '['))
        {
            $endPos = strlen($value) - 1;
            if (']' != $value[$endPos]) {
                return $ret;
            }
 
            $start = strrpos($value, '[') + 1;
            $name = substr($value, $start, $endPos - $start);
            $arrayName = substr($value, 0, $start-1);
            $ret = array(
                    'day' => $arrayName . '[' . $name . '_day' . ']',
                    'month' => $arrayName . '[' . $name . '_month'  . ']',
                    'year' => $arrayName . '[' . $name . '_year' . ']'
                    );
        }
        return $ret;
    }
}