/**
 * @module	 日历 
 * @creator  拔赤<lijing00333@163.com>
 */
KISSY.add('calendar', function(S, undefined) {

    function Calendar(trigger, config) {
        this._init(trigger, config);
    }

    S.augment(Calendar, {

		/**
		 * 日历构造函数
		 * @method 	_init
		 * @param { string }	selector
		 * @param { string }	config
		 * @private
		 */
        _init: function(selector, config) {
            var self = this,con = S.one(selector);
            self.id = self.C_Id = self._stamp(con);
            self._buildParam(config);

            /*
             self.con  日历的容器
             self.id   传进来的id
             self.C_Id 永远代表日历容器的ID
             */
            if (!self.popup) {
                self.con = con;
            } else {
                self.trigger = con;
                self.con = S.Node('<div></div>');
                S.one('body').append(self.con);
				self.C_Id = self._stamp(self.con);
                self.con.css({
                    'top':'0px',
                    'position':'absolute',
                    'background':'white',
                    'visibility':'hidden'
                });
            }

            //创建事件中心
            //事件中心已经和Calendar合并
            var EventFactory = new Function;
            S.augment(EventFactory, S.EventTarget);
            var eventCenter = new EventFactory();
            S.mix(self, eventCenter);

            self.render();
            self._buildEvent();
            return this;
        },

        render: function(o) {
            var self = this,
                i = 0,
                _prev,_next,_oym;

            o = o || {};
            self._parseParam(o);
            self.ca = [];

            self.con.addClass('ks-cal-call ks-clearfix multi-' + self.pages);
            self.con.html('');

            for (i = 0,_oym = [self.year,self.month]; i < self.pages; i++) {
                if (i == 0) {
                    _prev = true;
                } else {
                    _prev = false;
                    _oym = self._computeNextMonth(_oym);
                }
                _next = i == (self.pages - 1);
                self.ca.push(new self.Page({
                    year:_oym[0],
                    month:_oym[1],
                    prevArrow:_prev,
                    nextArrow:_next,
                    showTime:self.showTime
                }, self));


                self.ca[i].render();
            }
            return this;

        },

		/**
		 * 用以给容器打上id的标记,容器有id则返回
		 * @method _stamp
		 * @param { Kissy-Node }
		 * @return { string }
		 * @private
		 */
		_stamp: function(el){
			if(el.attr('id') == undefined || el.attr('id')==''){
				el.attr('id','K_'+S.now());
			}
			return el.attr('id');
		},

        /**
         * 计算d天的前几天或者后几天，返回date
		 * @method _showdate
		 * @private
         */
        _showdate: function(n, d) {
            var uom = new Date(d - 0 + n * 86400000);
            uom = uom.getFullYear() + "/" + (uom.getMonth() + 1) + "/" + uom.getDate();
            return new Date(uom);
        },

        /**
         * 创建日历外框的事件
		 * @method _buildEvent
		 * @private
         */
        _buildEvent: function() {
            var self = this;
            if (!self.popup)return this;
            //点击空白
            //flush event
            for (var i = 0; i < self.EV.length; i++) {
                if (self.EV[i] !== undefined) {
                    self.EV[i].detach();
                }
            }
            self.EV[0] = S.one('body').on('click', function(e) {
                //TODO e.target是裸的节点，这句不得不加，虽然在逻辑上并无特殊语义
                e.target = S.Node(e.target);
                //点击到日历上
                if (e.target.attr('id') == self.C_Id)return;
                if ((e.target.hasClass('ks-next') || e.target.hasClass('ks-prev'))
                    && e.target[0].tagName == 'A')    return;
                //点击在trigger上
                if (e.target.attr('id') == self.id)return;
                if (!S.DOM.contains(S.one('#' + self.C_Id), e.target)) {
                    self.hide();
                }
            });
            //点击触点
            for (i = 0; i < self.triggerType.length; i++) {

                self.EV[1] = S.one('#' + self.id).on(self.triggerType[i], function(e) {
                    e.target = S.Node(e.target);
                    e.preventDefault();
                    //如果focus和click同时存在的hack
                    S.log(e.type);
                    var a = self.triggerType;
                    if (S.inArray('click', a) && S.inArray('focus', a)) {//同时含有
                        if (e.type == 'focus') {
                            self.toggle();
                        }
                    } else if (S.inArray('click', a) && !S.inArray('focus', a)) {//只有click
                        if (e.type == 'click') {
                            self.toggle();
                        }
                    } else if (!S.inArray('click', a) && S.inArray('focus', a)) {//只有focus
                        setTimeout(function() {//为了跳过document.onclick事件
                            self.toggle();
                        }, 170);
                    } else {
                        self.toggle();
                    }

                });

            }
            return this;
        },

		/**
		 * 改变日历是否显示的状态
		 * @mathod toggle
		 */
        toggle: function() {
            var self = this;
            if (self.con.css('visibility') == 'hidden') {
                self.show();
            } else {
                self.hide();
            }
        },

        /**
         * 显示日历
		 * @method show
         */
        show: function() {
            var self = this;
            self.con.css('visibility', '');
            var _x = self.trigger.offset().left,
                //KISSY得到DOM的width是innerWidth，这里期望得到outterWidth
                height = self.trigger[0].offsetHeight || self.trigger.height(),
                _y = self.trigger.offset().top + height;
            self.con.css('left', _x.toString() + 'px');
            self.con.css('top', _y.toString() + 'px');
            return this;
        },

        /**
         * 隐藏日历
		 * @method hide
         */
        hide: function() {
            var self = this;
            self.con.css('visibility', 'hidden');
            return this;
        },

        /**
         * 创建参数列表
		 * @method _buildParam
		 * @private
         */
        _buildParam: function(o) {
            var self = this;
            if (o === undefined || o == null) {
                o = { };
            }

            function setParam(def, key) {
                var v = o[key];
                // null在这里是“占位符”，用来清除参数的一个道具
                self[key] = (v === undefined || v == null) ? def : v;
            }

			//这种处理方式不错
            S.each({
                date:        new Date(),
                startDay:    0,
                pages:       1,
                closable:    false,
                rangeSelect: false,
                minDate:     false,
                maxDate:     false,
                multiSelect: false,
                navigator:   true,
                popup:       false,
                showTime:    false,
                triggerType: ['click']
            }, setParam);

			// 支持用户传进来一个string
			if(typeof o.triggerType === 'string'){
				o.triggerType = [o.triggerType];
			}

            setParam(self.date, 'selected');
            if(o.startDay) self.startDay = (7 - o.startDay) % 7;

            if (o.range !== undefined && o.range != null) {
                var s = self._showdate(1, new Date(o.range.start.getFullYear() + '/' + (o.range.start.getMonth() + 1) + '/' + (o.range.start.getDate())));
                var e = self._showdate(1, new Date(o.range.end.getFullYear() + '/' + (o.range.end.getMonth() + 1) + '/' + (o.range.end.getDate())));
                self.range = {
                    start:s,
                    end:e
                };
            } else {
                self.range = {
                    start:null,
                    end:null
                };
            }
            self.EV = [];
            return this;
        },

        /**
         * 过滤参数列表
		 * @method _parseParam
		 * @private
         */
        _parseParam: function(o) {
            var self = this,i;
            if (o === undefined || o == null) {
                o = {};
            }
            for (i in o) {
                self[i] = o[i];
            }
            self._handleDate();
            return this;
        },

        /**
         * 模板函数
		 * @method _templetShow
		 * @private
         */
        _templetShow: function(templet, data) {
            var str_in,value_s,i,m,value,par;
            if (data instanceof Array) {
                str_in = '';
                for (i = 0; i < data.length; i++) {
                    str_in += arguments.callee(templet, data[i]);
                }
                templet = str_in;
            } else {
                value_s = templet.match(/{\$(.*?)}/g);
                if (data !== undefined && value_s != null) {
                    for (i = 0,m = value_s.length; i < m; i++) {
                        par = value_s[i].replace(/({\$)|}/g, '');
                        value = (data[par] !== undefined) ? data[par] : '';
                        templet = templet.replace(value_s[i], value);
                    }
                }
            }
            return templet;
        },

        /**
         * 处理日期
		 * @method _handleDate
		 * @private
         */
        _handleDate: function() {
            var self = this,
            date = self.date;
            self.weekday = date.getDay() + 1;//星期几 //指定日期是星期几
            self.day = date.getDate();//几号
            self.month = date.getMonth();//月份
            self.year = date.getFullYear();//年份
            return this;
        },

        //get标题
        _getHeadStr: function(year, month) {
            return year.toString() + '年' + (Number(month) + 1).toString() + '月';
        },

        //月加
        _monthAdd: function() {
            var self = this;
            if (self.month == 11) {
                self.year++;
                self.month = 0;
            } else {
                self.month++;
            }
            self.date = new Date(self.year.toString() + '/' + (self.month + 1).toString() + '/' + self.day.toString());
            return this;
        },

        //月减
        _monthMinus: function() {
            var self = this;
            if (self.month == 0) {
                self.year--;
                self.month = 11;
            } else {
                self.month--;
            }
            self.date = new Date(self.year.toString() + '/' + (self.month + 1).toString() + '/' + self.day.toString());
            return this;
        },

        //裸算下一个月的年月,[2009,11],年:fullYear，月:从0开始计数
        _computeNextMonth: function(a) {
            var _year = a[0],
                _month = a[1];
            if (_month == 11) {
                _year++;
                _month = 0;
            } else {
                _month++;
            }
            return [_year,_month];
        },

        //处理日期的偏移量
        _handleOffset: function() {
            var self = this,
                data = ['日','一','二','三','四','五','六'],
                temp = '<span>{$day}</span>',
                offset = self.startDay,
                day_html = '',
                a = [];
            for (var i = 0; i < 7; i++) {
                a[i] = {
                    day:data[(i - offset + 7) % 7]
                };
            }
            day_html = self._templetShow(temp, a);

            return {
                day_html:day_html
            };
        },

        //处理起始日期,d:Date类型
        _handleRange: function(d) {
            var self = this,t;
            if ((self.range.start == null && self.range.end == null ) || (self.range.start != null && self.range.end != null)) {
                self.range.start = d;
                self.range.end = null;
                self.render();
            } else if (self.range.start != null && self.range.end == null) {
                self.range.end = d;
                if (self.range.start.getTime() > self.range.end.getTime()) {
                    t = self.range.start;
                    self.range.start = self.range.end;
                    self.range.end = t;
                }
                self.fire('rangeSelect', self.range);
                self.render();
            }
            return this;
        }
    });

    S.Calendar = Calendar;
}, { requires: ['core'] } );

/**
 * 2010-09-09 by lijing00333@163.com - 拔赤
 *     - 将基于YUI2/3的Calendar改为基于KISSY
 *     - 增加起始日期（星期x）的自定义
 *      - 常见浮层的bugfix
 *
 * TODO:
 *   - 日历日期的输出格式的定制
 *   - 多选日期的场景的交互设计
 */
