/*
 * @name:    datepicker
 * @version: 0.1 
 * @release: 2008-12-09
 * @type:    jQuery plugin  
 * @author:  David Sklar
--------------------------------------- */

if(!datepicker) var datepicker = {};

jQuery.extend(datepicker, {
  txt: []
});

(function ($) {
    $.fn.datepicker = function (opt) {
    
    var options = $.extend(datepicker, {
      format:   'dd.mm.YYYY HH:ii',
      base:     'js/datepicker/',
      lang:     'cs',
      langPath: 'lang/',
      cssFile:  'css/datepicker.css',
      cssName:  {box: 'picker', trigger: 'picker-trigger'}, 
      buttons:  {
                open:     'gfx/ico_open.png',
                previous: 'gfx/ico_prev.gif',
                next:     'gfx/ico_next.gif',
                close:    'gfx/ico_close.gif'
                }
    }, opt);

    /*---------------------------*/    
    var box =       [];
    
    var inputBox =  [];
    var outputBox = [];

    var btnOpen =   [];
    var btnPrev =   [];
    var btnNext =   [];
    var btnClose =  [];

    var status =    [];

    var minute, hour, day, month, clickmonth, year, timestamp, now, stack;

    var origin = new Date();
    origin.setTime(Date.parse(origin.toString().substr(4,3) +' 1 '+ origin.getFullYear() +' 00:00:00'));
    var time = [];
    time['load'] = Date.parse(origin);


    // css
    var sheet = $('<link rel="stylesheet" type="text/css" href="'+ options.base + options.cssFile +'" media="screen" />');
    $('head').append(sheet);
    /*
    $.ajax({
        url:      options.base + options.cssFile, 
        async:    false,
        dataType: 'text'
    });
    */

    // lokalizace
    if (!datepicker.txt[options.lang]) {
      $.ajax({
          url:      options.base + options.langPath + options.lang +'.js', 
          async:    false,
          dataType: 'script'
      });
    }
    var days = new Array(31,28,31,30,31,30,31,31,30,31,30,31);  
    var mon = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');  
    var wdays = datepicker.txt[options.lang].wdays;
    var months = datepicker.txt[options.lang].months;

    //close dp on click outside
    var base = $.browser.msie ? $('html') : $(window);
    base.bind('mousedown', function (e) {  
        var target = e.target;
        if (!$(target).parents().is('.'+ options.cssName.box) && !$(target).is('.'+ options.cssName.trigger)) {
            close();
        }
    });


    /*--------------------------- */
    var open = function (index) {
      //
      now = parse(index);
      timestamp = Date.parse(now);
      time['open'] = Date.parse(new Date());

      minute = now.getMinutes();
      hour =   now.getHours();
      day =    now.getDate();
      month =  now.getMonth();
      clickmonth =  now.getMonth();
      year =   now.getFullYear();
      
      close();
      draw(index);

      $('body').append(box[index]);

      //~ var t = box[index].find('table');
      //~ var w = t.width() + parseInt(t.css('borderRightWidth').match(/(.+)px/i)[1]) + parseInt(t.css('borderLeftWidth').match(/(.+)px/i)[1]);
      //~ var h = t.height() + parseInt(t.css('borderTopWidth').match(/(.+)px/i)[1]) + parseInt(t.css('borderBottomWidth').match(/(.+)px/i)[1]);
      
      var dv = box[index].find('div.boundingbox');
      var w = dv.width() + parseInt(dv.css('borderRightWidth').match(/(.+)px/i)[1]) + parseInt(dv.css('borderLeftWidth').match(/(.+)px/i)[1]);
      var h = dv.height() + parseInt(dv.css('borderTopWidth').match(/(.+)px/i)[1]) + parseInt(dv.css('borderBottomWidth').match(/(.+)px/i)[1]);
      
      var dx = $.browser.msie ? 0 : parseInt(btnOpen[index].css('marginRight').match(/(.+)px/i)[1]);
      //~ var x = btnOpen[index].offset().left + btnOpen[index].width() + dx + 2;
      var x = btnOpen[index].offset().left - w - 4;
      var y = btnOpen[index].offset().top - h/2 + btnOpen[index].height()/2;

      box[index]
          .width(w)
          .height(h)
          .css({'top': y, 'left': x, 'opacity': 0})
          .slideDown({ 
              duration: 300, 
              complete: function () {
                          $(this).animate({
                            opacity: 1.0
                          }, 200);

                          status[index] = true;
                          //
                          if (!$.browser.opera) {
                            $(this).find('td.set a').focus();
                          }
                          // msie focus
                          if ($.browser.msie) {
                            $(this)
                                .find('tbody a')
                                .bind('focus', function (e) {
                                  var target = e.target;
                                  $(target).addClass('focus');
                                })
                                .bind('blur', function (e) {
                                  var target = e.target;
                                  $(target).removeClass('focus');
                                });
                          }
                        }
          });
    };

    // 
    var set = function (index, e) {
      var time, day, clickmonth, target = e.target, tmp; 
      var m = month + 1;

      if ($(target).is('a')) {
        day = parseInt($(target).html()); 
        clickmonth = month;

        if (!isNaN(day)) {
          day = day < 10 ? '0'+ day : day;
          m = parseInt(m) < 10 ? '0'+ m : m;
          time = inputBox[index].val();
                   
          tmp = options.format.replace(/dd/, day);
          tmp = tmp.replace(/mm/, m);
          tmp = tmp.replace(/YYYY/, year);
          tmp = tmp.replace(/HH:ii/, time);
          
          outputBox[index].val(tmp);
          close();
        }
      } 

      e.preventDefault(e);
    };

    // @return Date object
    var parse = function (index) {
      var format = options.format;
      var value = outputBox[index].val();

      var tmp = format.replace(/dd/, '\\d{2}');
      tmp = tmp.replace(/mm/, '\\d{2}');
      tmp = tmp.replace(/YYYY/, '\\d{4}');
      tmp = tmp.replace(/HH/, '\\d{2}');
      tmp = tmp.replace(/ii/, '\\d{2}');

      var regexp = new RegExp(tmp);
      if (regexp.test(value)) {
        var day =   parseInt(value.substr(format.indexOf('dd'), 2), 10);
        var month = parseInt(value.substr(format.indexOf('mm'), 2), 10) - 1;
        var year =  parseInt(value.substr(format.indexOf('YYYY'), 4), 10);
        var hour =  parseInt(value.substr(format.indexOf('HH'), 2), 10);
        var minute = parseInt(value.substr(format.indexOf('ii'), 2), 10);
      }

      var d =   new Date();
      d.setFullYear(year);
      d.setMonth(month, day);
      d.setHours(hour, minute, 0, 0);

      return (isNaN(d.getTime()) ? new Date() : d);
    };

    var prev = function (index) {
      month--;
      if (month < 0) {
        month = 11; year--;
      }
      //first day of prev month
      timestamp = Date.parse(mon[month] +' 1, '+ year);
      draw(index);
    };

    var next = function (index) {
      month++;
      if (month > 11) {
        month = 0; year++;
      }
      //first day of next month
      timestamp = Date.parse(mon[month] +' 1, '+ year);
      draw(index);
    };

    //CLOSE
    var close = function () {
      $(box).each(function (i) {
        box[i].html('');
        $('div.picker').remove(); //removes dp from DOM
        status[i] = false;
      });
    };

    //DRAW
    var draw = function (index) {
      now.setTime(timestamp);

      // prvni den v mesici
      var d =  new Date();
      d.setTime(Date.parse(now.toString().substr(4,3) +' 1, '+ year));
      //firstDay bude cislo dne v tydnu, transformace na Mon=0 Sun=6
      var firstDay = d.getDay() - 1;
      if (firstDay < 0) {firstDay = 6;}
      
      // prestupny rok
      days[1] = year%4 == 0 ? 29 : 28;

      // mesic aktualniho dne / pro test dnesku
      today = new Date();
      today_day =  today.getDate();
      today_month =  today.getMonth();
      
      /* sablona kalendare
      ------------------------------- */
      var tpl = '<div class="boundingbox"><table cellspacing="1">';

      // hlava 
      tpl += '<thead>';
      tpl += '<tr><th></th><th colspan="5">'+ months[month] +' '+ year +'</th><th></th></tr>';
      tpl += '</thead>';

      tpl += '<tr id="wdays">';
      for (var i = 0; i < 7 ; i++) {
        tpl += '<td>' + wdays[i] + '</td>';  
      }
      tpl += '</tr>';

      // telo
      var rows = Math.ceil((firstDay + days[month])/7);
      var k = 0;  // bunka
      var l = 1;  // den

      for (var i = 0; i < rows; i++) {
        tpl += '<tr>';
        for (var j = 0; j < 7; j++) {
            if (k >= firstDay && l <= days[month]) {
                if ((l == today_day) && (month == today_month)) {
                    //~ alert(today_day+';'+day+';'+clickmonth);
                    tpl += '<td class="'+(l == day ? 'selected' : 'today')+'"><a href="">'+ l +'</a></td>';
                } else if ((l == day) && (month == clickmonth)) {
                    tpl += '<td class="selected"><a href="">'+ l +'</a></td>';
                } else {
                    tpl += '<td><a href="">'+ l +'</a></td>';
                }
                l++;
            } else {
                tpl += '<td></td>';
            }
            k++;
        }
        tpl += '</tr>';
      }

      // pata
      var h = hour > 9 ? hour : '0'+ hour;
      var m = minute > 9 ? minute : '0'+ minute;

      //~ tpl += '<tfoot>';
      //~ tpl += '<tr><td colspan="6" class="left"></td><td></td></tr>';
      //~ tpl += '</tfoot>'; 

      tpl += '</table></div>';


      // opera
      if ($.browser.opera) {
        box[index].addClass('opera');
      }

      box[index].html(tpl)
                .bind('keydown', function (e) {
                  if (e.keyCode == 13) {
                    set(index, e);
                    e.preventDefault(e);
                  }
                });
      box[index].find('thead th:first')
                .append(btnPrev[index])
                .bind('click', function (e) {
                  e.preventDefault(e); 
                })
                .bind('mousedown', function () {
                  prev(index); 
                })
                .bind('keydown', function (e) {
                  if (e.keyCode == 13) {
                    prev(index);
                    e.preventDefault(e);
                  }
                });
      box[index].find('thead th:last')
                .append(btnNext[index])
                .bind('click', function (e) {
                  e.preventDefault(e);
                })
                .bind('mousedown', function () {
                  next(index);
                })
                .bind('keydown', function (e) {
                  if (e.keyCode == 13) {
                    next(index);
                    e.preventDefault(e);
                  }
                });
      box[index].find('tbody a')
                .bind('mousedown', function (e) {
                  e.preventDefault(e);
                  set(index, e);
                  close();
                });
      //close button appending
      /*box[index].find('tfoot td:last')
                .append(btnClose[index])
                .bind('click', function (e) {
                  close(); 
                  e.preventDefault(e);
                })
                .bind('keydown', function (e) { //
                  if (e.keyCode == 13) {
                    close(index);
                    e.preventDefault(e);
                  }
                });*/
      
      //setup h : m
      //~ inputBox[index].val(h +':'+ m);
      //append hours : minutes
      //~ box[index].find('tfoot td:first').append(inputBox[index]);
    };



    /*
    --------------------------- */
    return this.each(function (index) {
      var $this = $(this);
  
      box[index] =      $('<div class="'+ options.cssName.box +'"></div>');
  
      btnOpen[index] =  $('<a href="#" class="'+ options.cssName.trigger +'"><img src="'+ options.base + options.buttons.open +'" alt="" /></a>');
      btnPrev[index] =  $('<a href="" title="'+ datepicker.txt[options.lang].previous +'"><img src="'+ options.base + options.buttons.previous +'" alt="'+ datepicker.txt[options.lang].previous +'" /></a>');
      btnNext[index] =  $('<a href="" title="'+ datepicker.txt[options.lang].next +'"><img src="'+ options.base + options.buttons.next +'" alt="'+ datepicker.txt[options.lang].next +'" /></a>');
      btnClose[index] = $('<a href="" title="'+ datepicker.txt[options.lang].close +'"><img src="'+ options.base + options.buttons.close +'" alt="'+ datepicker.txt[options.lang].close +'" /></a>');
  
      inputBox[index] =   $('<input type="text" />');
      outputBox[index] =  $this;
      
      status[index] = false;
  
      //
      $this.after(btnOpen[index]); 
      btnOpen[index]
          .bind('focus click', function (e) {
            if (!status[index]) {
              open(index);
            }
            e.preventDefault(e);
          });
  
      //
      base.bind('keydown', function (e) { 
            // d, n, up, right
            if (status[index] && (e.keyCode == 68 || e.keyCode == 78 || e.keyCode == 38 || e.keyCode == 39)) {
              next(index);
              e.preventDefault(e); 
            }
            // p, down, left
            if (status[index] && (e.keyCode == 80 || e.keyCode == 40 || e.keyCode == 37)) {
              prev(index);
              e.preventDefault(e);
            }
            // Esc, z, c
            if (status[index] && (e.keyCode == 27 || e.keyCode == 90 || e.keyCode == 67)) {
              close(index);
              e.preventDefault(e);
            }            
          });
  
    }); 
  };
})(jQuery);
