/*
 *  Copyright : Tenerlab ©
 */

(function($){

  var window = this;

	DatePicker = window.DatePicker = function(el, options) {
    DatePicker.fn = DatePicker.prototype = {


      strDate: null,
      // selected - Object {<year> : Object {<month> : Object {<date> : boolean }}}
      selected: {},

      init: function(el, options) {
        // Handle $(DOMElement)
        if (el.nodeType) {
          _this = el;
          // cache jquery object to avoid multiple constructor call
          $_this = $(_this);

          _setDefaultOptions();
          // copy all public methods and propreties
          $.extend(_this, DatePicker.fn);
          // copy initialisation options
          _setOptions(options);
          _drawDatePicker();
          
          return _this;
        }
        // Handle HTML strings
        if (typeof el === "string") {
          return DatePicker(document.getElementById(el), options);
        }
      },
      bind: function(event, handler) {
        $(this).bind(event, handler);
      },
      unbind: function(event) {
        $(this).unbind(event);
      },
      show: function() {
        $_this.show();
        _isVisible = true;
        if (_viewToggle) {
          $(_viewToggle).hide();
        }
      },
      hide: function() {
        $_this.hide();
        _isVisible = false;
        if (_viewToggle) {
          $(_viewToggle).show();
        }
      },
      /**
       * Gets the selected dates
       * @return Object {<year> : Object {<month> : Object {<date> : boolean }}}
       */
      getValue: function() {
        return _this.selected;
      },
      /**
       * Sets the selected dates and redraws the DatePicker
       * @param dates - Object {<year> : Object {<month> : Object {<date> : boolean }}}
       */
      setValue: function(dates) {

        _reset();
        _this.selected = dates;
        
        $_this.find(".active-day").each(function(key, el) {_toggleCellsClassname(el);});
        
      }
    }
    // private variables
    var _marginLeft = 0;
    var _firstMonth;
    var _lastMonth;

    var _monthNameSpan;
    var _yearNameSpan;

    var _selectedMonths = new Array();
    var _selectedWeeks = new Array();
    var _selectedDayWeeks = new Array();
    
    var _this;
    var $_this;
    var _options;
    var _viewToggle;
    var _isVisible = true;

    return new DatePicker.fn.init(el, options);

    // set default public options
    function _setDefaultOptions() {
      
      var now = new Date();
      // private
      _firstMonth = new Date();
      _lastMonth = new Date();
      _firstMonth.setDate(1);
      _lastMonth.setDate(1);

      _this.shownMonth = now.getMonth();
      _this.shownYear = now.getFullYear();

      _firstMonth.setMonth(now.getMonth());
      _lastMonth.setMonth(now.getMonth());
      _firstMonth.setFullYear(now.getFullYear());
      _lastMonth.setFullYear(now.getFullYear());



      _options = new Object();
      _options.weekControl = false;
      _options.dayWeekControl = false;
      _options.monthControl = false;
      _options.defaultView = 'expanded';

      // public
      _options.lang = 'ro';
      // TODO: get current day acording to timezone
      // (it may be Sunday - 0  instead of Monday - 0)
      _this.shownDay = now.getDay();
      _this.shownDate = now.getDate();

      
      _viewToggle = null;

      // array of selected dates
      _this.selected = new Object();
      return _this;
    }

    function _setOptions(options) {
      if (typeof options != 'object') {
        return;
      }
      $.extend(_options, options);
      if (typeof options.viewToggle != 'undefined') {
        _viewToggle = document.getElementById(options.viewToggle);
        if (_viewToggle) {
          $(_viewToggle).click(_toggleView);
        }
      }
    }

    // private functions
    function _drawWeekdayCells() {
      switch(_options.lang) {
        case 'ru':
          return '<div class="week"><div class="empty-cell"></div><div class="select-day-week">Пн</div><div class="select-day-week">Вт</div><div class="select-day-week">Ср</div><div class="select-day-week">Чт</div><div class="select-day-week">Пт</div><div class="select-day-week">Сб</div><div class="select-day-week">Вс</div></div>';
        case 'en':
          return '<div class="week"><div class="empty-cell"></div><div class="select-day-week">Mo</div><div class="select-day-week">Tu</div><div class="select-day-week">We</div><div class="select-day-week">Th</div><div class="select-day-week">Fr</div><div class="select-day-week">Sa</div><div class="select-day-week">Su</div></div>';
        default:
          return '<div class="week"><div class="empty-cell"></div><div class="select-day-week">Lu</div><div class="select-day-week">Ma</div><div class="select-day-week">Mi</div><div class="select-day-week">Jo</div><div class="select-day-week">Vi</div><div class="select-day-week">Si</div><div class="select-day-week">Du</div></div>';
      }
    }

    function _drawCells(year, month) {

      var shownMonth = new Date();
      shownMonth.setDate(1);
      shownMonth.setMonth(month);
      shownMonth.setYear(year);
      //first day of week
      var firstDate = (shownMonth.getDay() - 1 < 0)?6:shownMonth.getDay() - 1;
      //last day of month
      var nextMonth = new Date(shownMonth);
      nextMonth.setMonth((month + 1 > 11) ? 0 : month + 1);
      nextMonth = new Date(nextMonth.getTime() - 86400000);
      var lastDate = nextMonth.getDate();
      
      //last day of prev month
      shownMonth = new Date(shownMonth.getTime() - 86400000);
      var prevMonthLastDate = shownMonth.getDate();
      var week = 0;
      var html = '<div class="month">' +_drawWeekdayCells();
      if (firstDate != 0) {
        html += '<div class="select-week"></div>';
        week++;
        for(i=prevMonthLastDate-firstDate+1; i<=prevMonthLastDate; i++) {
          html += '<div class="inactive">'+ i + '</div>';
        }
      }
      
      for(i=0; i<lastDate; i++) {
        if((firstDate + i) % 7 == 0) {
          week++;
          html += '<div class="select-week"></div>';
        }
        var day = i + 1;
        html += '<div class="active-day' + _generateCellClass(year, month, day) + '"'
                + ' _year="' + year + '" _month="' + month + '" _day="' + day + '">' + day + '</div>';
      }
      
      // insert next week days
      if ((firstDate + i) % 7 != 0) {
        var weekday = 7 - ((firstDate + i) % 7);
        for(i=0; i<weekday; i++) {
          html += '<div class="inactive">'+ (i+1) +'</div>';
        }
      }
      while(week < 6) {
        week++;
        html += '<div class="select-week"></div><div class="inactive"></div><div class="inactive"></div><div class="inactive"></div><div class="inactive"></div><div class="inactive"></div><div class="inactive"></div><div class="inactive"></div>';
      }
      html += '</div>';
      return html;
    }

    function _drawDatePicker() {
      _this.innerHTML =  _drawControls() + '<div class="months" style="margin-left:0px">' + _drawCells(_this.shownYear, _this.shownMonth) + '</div>';
      $_this.addClass('datepicker');

      _monthNameSpan = $_this.find('.month-name')[0];
      _yearNameSpan = $_this.find('.year-name')[0];
      $_this.find('.month').addClass('selected');
      
      _addControls();
      _addCellControls();
      _addMonthToLeft();
      _addMonthToRight();
      
      if (_options.defaultView == 'collapsed') {
        _this.hide();
      }
    }

    function _addMonthToLeft() {
      var year = _firstMonth.getFullYear();
      var month = _firstMonth.getMonth();
      if (--month < 0) {
        month += 12;
        year--;
      }

      _firstMonth.setFullYear(year);
      _firstMonth.setMonth(month);

      var $months = $($_this.find('.months'));
      $months.prepend(_drawCells(year, month));

      _moveTo(_marginLeft-174);
    }
    
    function _addMonthToRight() {
      var year = _lastMonth.getFullYear();
      var month = _lastMonth.getMonth();
      if (++month > 11) {
        month -= 12;
        year++;
      }
      _lastMonth.setFullYear(year);
      _lastMonth.setMonth(month);

      var $months = $($_this.find('.months'));
      $months.append(_drawCells(year, month));
    }

    function _removeMonthFromLeft() {
      var year = _firstMonth.getFullYear();
      var month = _firstMonth.getMonth();
      if (++month > 11) {
        month -= 12;
        year++;
      }
      _firstMonth.setFullYear(year);
      _firstMonth.setMonth(month);
      $_this.find('.month:first').remove();
      _moveTo(_marginLeft+174);
    }

    function _removeMonthFromRight() {
      var year = _lastMonth.getFullYear();
      var month = _lastMonth.getMonth();
      if (--month < 0) {
        month += 12;
        year--;
      }
      _lastMonth.setFullYear(year);
      _lastMonth.setMonth(month);
      $_this.find('.month:last').remove();
    }

    function _slideLeft() {
      _removeControls();
      $_this.find('.month').removeClass('selected');
      $($_this.find('.month')[1]).addClass('selected');

      if (++_this.shownMonth > 11) {
        _this.shownMonth -= 12;
        _this.shownYear++;
      }
      _marginLeft -= 174;
      $_this.find('.months').animate({marginLeft:_marginLeft+'px'}, 500, _addControls);
      _drawMonthName();

    }
    
    function _slideRight() {
      _removeControls();
      $_this.find('.month').removeClass('selected');
      $($_this.find('.month')[1]).addClass('selected');
      
      if (--_this.shownMonth < 0) {
        _this.shownMonth += 12;
        _this.shownYear--;
      }
      _marginLeft += 174;
      $_this.find('.months').animate({marginLeft:_marginLeft+'px'}, 500, _addControls);
      _drawMonthName();
    }

    function _moveTo(margin) {
      _marginLeft = margin;
      var months = $_this.find('.months')[0];
      months.style.marginLeft = _marginLeft + 'px';
    }

    function _drawControls() {
      return '<div class="controls"><a class="prev-month" href="javascript:void(0)"><img src="/images/prev-month.gif"></a><div class="month-name">' + _getMonthName(_this.shownMonth) + '</div> <div class="year-name">'+_this.shownYear+'</div><a class="next-month" href="javascript:void(0)"><img src="/images/next-month.gif"></a></div>';
    }

    function _removeControls() {
      $_this.find('div.month-name').unbind('click');
      $_this.find('div.year-name').unbind('click');
      $_this.find('a.next-month').unbind('click');
      $_this.find('a.prev-month').unbind('click');
      $_this.find('a.select-week').unbind('click');
      $_this.find('a.select-day-week').unbind('click');
    }

    function _addControls() {
      if (_options.monthControl) {
        $_this.find('div.month-name').unbind('click').bind('click', _toggleSelectMonth)
          .bind('mouseenter', function(){$(this).parent().find('.year-name, .month-name').addClass('hover-month');})
          .bind('mouseleave', function(){$(this).parent().find('.year-name, .month-name').removeClass('hover-month');});
        $_this.find('div.year-name').unbind('click').bind('click', _toggleSelectMonth)
          .bind('mouseenter', function(){$(this).parent().find('.year-name, .month-name').addClass('hover-month');})
          .bind('mouseleave', function(){$(this).parent().find('.year-name, .month-name').removeClass('hover-month');});
      }
      if (_options.weekControl) {
        $_this.find('.month.selected').find('.select-week').each(function (key, elem) {
          $(elem).unbind('click').bind('click', function(){_toggleSelectWeek(key);});
        });
      }
      if(_options.dayWeekControl) {
        $_this.find('.month.selected').find('.select-day-week').each(function (key, elem) {
          $(elem).unbind('click').bind('click', function(){_toggleSelectDayWeek(key);});
        });
      }

      $_this.find('a.next-month').unbind('click').bind('click', _nextMonth);
      $_this.find('a.prev-month').unbind('click').bind('click', _prevMonth);
    }

    function _prevMonth() {
      _addMonthToLeft();
      _removeMonthFromRight();
      _slideRight();
      _drawMonthName();
      _addCellControls();
    }

    function _nextMonth() {
      _addMonthToRight();
      _removeMonthFromLeft();
      _slideLeft();
      _drawMonthName();
      _addCellControls();
    }
    
    function _getMonthName(month) {
      var months = {
        'ro': ['Ianuarie', 'Februarie', 'Martie','Aprilie', 'Mai','Iunie','Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
        'ru': ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
        'en': ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
      }
      return months[_options.lang][month];
    }

    function _addCellControls() {
      $_this.find('.active-day').unbind('click').bind ('click', function(elem){
        _toggleSelectDate(elem.currentTarget);
      });
    }

    function _generateCellClass(year, month, date) {
      month++;
      var retString = '';
      if(typeof _this.selected[year] != 'undefined'
          && typeof _this.selected[year][month] != 'undefined'
          && typeof _this.selected[year][month][date] != 'undefined'
          && _this.selected[year][month][date] == true) {
            retString += ' selected';
      }
      var shownDate = new Date(year, month - 1, date);

      if(shownDate.getDay() == 0 || shownDate.getDay() == 6) {
        retString += ' weekend';
      }
      
      var today = new Date();
      if (today.getDate() == date && today.getMonth() == month - 1 &&
        today.getFullYear() == year) {
          retString += ' today';
        }

      return retString;
    }

    /**
     * Updates cell's "selected" classname according to _this.selected object
     */
    function _toggleCellsClassname(elem) {

      var $elem = $(elem);
      var day = parseInt(elem.getAttribute('_day'));
      var month = parseInt(elem.getAttribute('_month')) + 1;
      var year = parseInt(elem.getAttribute('_year'));

      _initializeDatesArray(year, month, day);

      if(_this.selected[year][month][day]) {
        $elem.addClass('selected');
      }
      else {
        $elem.removeClass('selected');
      }
    }

    function _toggleSelectDate(elem, force, fire) {
      
      var day = parseInt(elem.getAttribute('_day'));
      var month = parseInt(elem.getAttribute('_month')) + 1;
      var year = parseInt(elem.getAttribute('_year'));

      _initializeDatesArray(year, month, day);

      if (typeof force != 'undefined') {
        _this.selected[year][month][day] = !force;
      }

      if(!_this.selected[year][month][day]) {
        _this.selected[year][month][day] = true;
      }
      else {
        _this.selected[year][month][day] = false;
      }
      
      _toggleCellsClassname(elem);
      
      if (month < 10) {
        month = '0' + month;
      }
      if (day < 10) {
        day = '0' + day;
      }
      _this.strDate = year + '-' + month + '-' + day + ' 00:00';
      if (typeof fire == 'undefined' || fire) {
        _fireEvent('selected');
      }
    }

    /**
     * Initializes year's and month's array for a given date
     */
    function _initializeDatesArray(year, month, day) {
      
      if(typeof _this.selected[year] == 'undefined') {
        _this.selected[year] = new Object();
        _this.selected[year][month] = new Object();
        _this.selected[year][month][day] = false;
      }
      else if (typeof _this.selected[year][month] == 'undefined') {
        _this.selected[year][month] = new Object();
        _this.selected[year][month][day] = false;
      }
      else if (typeof _this.selected[year][month][day] == 'undefined') {
        _this.selected[year][month][day] = false;
      }
    }

    function _toggleSelectMonth() {

      var key = _this.shownYear + '_' + _this.shownMonth;
      if (typeof _selectedMonths[key] == 'undefined') {
        _selectedMonths[key] = true;
      }
      else {
        _selectedMonths[key] = !_selectedMonths[key];
      }
      for (i=0; i<7; i++) {
        _selectedWeeks[key + '_' + i] = _selectedMonths[key];
      }

      var $this_month = $($_this.find('.month')[1]);
      $this_month.find('.select-week').each(function(){
        var $_select_week = $(this);
        if ($_select_week.hasClass('is-selected-week'))
          $_select_week.removeClass('is-selected-week');
        else
          $_select_week.addClass('is-selected-week');
      });
      $this_month.find('.active-day').each(function(foo, elem) {
        _toggleSelectDate(elem, _selectedMonths[key], false);
      });

      _fireEvent('selected');
    }

    function _toggleSelectWeek(week) {

      var shownMonth = new Date();
      shownMonth.setMonth(_this.shownMonth);
      shownMonth.setYear(_this.shownYear);
      shownMonth.setDate(1);
      //first day of week
      var firstDate = (shownMonth.getDay() - 1 < 0)?6:shownMonth.getDay() - 1;
      
      var $_select_week = $($($_this.find('.month')[1]).find('.select-week')[week]);
      if ($_select_week.hasClass('is-selected-week'))
        $_select_week.removeClass('is-selected-week');
      else
        $_select_week.addClass('is-selected-week');

      var days = $($_this.find('.month')[1]).find('.active-day');
      var startDate = (week*7 - firstDate < 0)? 0 : week*7 - firstDate;
      var endDate = (week*7 + 7 - firstDate >= days.length)? days.length : week*7 + 7 - firstDate;
      
      var key = _this.shownYear + '_' + _this.shownMonth + '_' + week;
      if (typeof _selectedWeeks[key] == 'undefined') {
        _selectedWeeks[key] = true;
      }
      else {
        _selectedWeeks[key] = !_selectedWeeks[key];
      }
      for (i=startDate; i<endDate; i++) {
        _toggleSelectDate(days[i], _selectedWeeks[key], false);
      }

      _fireEvent('selected');
    }

    function _toggleSelectDayWeek(dayWeek) {

      var shownMonth = new Date();
      shownMonth.setMonth(_this.shownMonth);
      shownMonth.setYear(_this.shownYear);
      shownMonth.setDate(1);
      //first day of week
      var firstDay = (shownMonth.getDay() - 1 < 0)?6:shownMonth.getDay() - 1;
      // first Date of day of week
      var firstDate = (dayWeek < firstDay)? 8 + dayWeek - firstDay: 1+dayWeek-firstDay;
      var days = $($_this.find('.month')[1]).find('.active-day');
      var key = _this.shownYear + '_' + _this.shownMonth + '_' + dayWeek;
      if (typeof _selectedDayWeeks[key] == 'undefined') {
        _selectedDayWeeks[key] = true;
      }
      else {
        _selectedDayWeeks[key] = !_selectedDayWeeks[key];
      }
      for(var endDate = firstDate; endDate <= days.length; endDate+=7){
        _toggleSelectDate(days[endDate-1], _selectedDayWeeks[key], false);

      }
      _fireEvent('selected');
    }


    function _drawMonthName() {
      _monthNameSpan.innerHTML = _getMonthName(_this.shownMonth);
      _yearNameSpan.innerHTML = _this.shownYear;
    }

    function _fireEvent(event) {
      $_this.trigger(event, _this);
      if (_viewToggle)
        _reset();
    }

    function _toggleView() {
      if (_isVisible) {
        _this.hide();
      }
      else {
        _this.show();
      }
    }
    function _reset() {
      _this.selected = new Object();
      _selectedMonths = new Array();
      _selectedWeeks = new Array();
      _selectedDayWeeks = new Array();
      $_this.find('.selected').removeClass('selected');
    }
    
	};
})(jQuery);
