(function($) {
  $.fn.ypscalendar = function(options) {
    /**
     * Default settings
     */

    var defaults = {
      startInput: '#arrivalPicker',
      endInput: '#departurePicker',
      dateFormat: 'd.m.yy',
      minDate: +1,
      maxDate: '+1y',
      range: +1,

      startAlt: {
        date: undefined,
        month: undefined,
        year: undefined,
        monthYear: undefined
      },

      endAlt: {
        date: undefined,
        month: undefined,
        year: undefined,
        monthYear: undefined
      }
    };

    /**
     * Initial setup
     */
    var options = $.extend(defaults, options);

    /**
     * Some dates...
     */
    var today = new Date();
    var minStartDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + options.minDate);
    var minEndDate = undefined;
    var startDate = undefined;
    var endDate = undefined;

    /**
     * Inputs
     */
    var startInput = $(options.startInput);
    var endInput = $(options.endInput);
    var startAltInputs = {
      date: options.startAlt.date ? $(options.startAlt.date) : null,
      month: options.startAlt.month ? $(options.startAlt.month) : null,
      year: options.startAlt.year ? $(options.startAlt.year) : null,
      monthYear: options.startAlt.monthYear ? $(options.startAlt.monthYear) : null
    };
    var endAltInputs = {
      date: options.endAlt.date ? $(options.endAlt.date) : null,
      month: options.endAlt.month ? $(options.endAlt.month) : null,
      year: options.endAlt.year ? $(options.endAlt.year) : null,
      monthYear: options.endAlt.monthYear ? $(options.endAlt.monthYear) : null
    };

    /**
     * Set minimal dates before show
     */
    var setMinDate = function(input) {
      return {
        minDate: $(this).hasClass('first') ? minStartDate : minEndDate
      };
    }

    /**
     * Set alt fields and correct min dates
     */
    var onSelect = function(dateText, inst) {
      disabled = endInput.datepicker('isDisabled');

      // selected date
      var d = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay);
      // first or second input?
      if ($(this).hasClass('first')) {
        startDate = d;
        // set end minimal date = startDate + range
        minEndDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + options.range);
        endInput.datepicker('option', 'minDate', minEndDate);
        if (minEndDate > endDate) {
          // if minimal end date is after endDate - set endDate = minEndDate
          endDate = minEndDate;
          endInput.datepicker('setDate', endDate);
          setAltFields(endAltInputs, endDate);
        }
      } else {
        endDate = d;
      }
      // fill alt fields
      setAltFields($(this).hasClass('first') ? startAltInputs : endAltInputs, d);

      if (disabled) {
        endInput.datepicker('disable');
      }
    }

    var monthToString = function(month) {
      // js months are 0-11
      month++;

      if (month < 10) {
        return "0"+month;
      } else {
        return ""+month;
      }
    }

    /**
     * Fill alternative fields
     */
    var setAltFields = function(altFields, date) {
      if (altFields.date) {
        altFields.date.val(date.getDate());
      }
      if (altFields.month) {
        altFields.month.val(monthToString(date.getMonth()));
      }
      if (altFields.year) {
        altFields.year.val(date.getFullYear());
      }
      if (altFields.monthYear) {
        altFields.monthYear.val(monthToString(date.getMonth()) + '-' + date.getFullYear());
      }
    }

    /**
     * Default date for input based on old ones
     */
    var getDefaultDate = function(altFields, interval) {
      var d = m = y = my = undefined;

      // check vals in alt fields
      if (altFields.date) {
        d = $(altFields.date).val();
        //console.debug('d = ' + d);
      }
      if (altFields.month) {
        m = $(altFields.month).val();
        //console.debug('m = ' + m);
      }
      if (altFields.year) {
        y = $(altFields.year).val();
        //console.debug('y = ' + y);
      }
      if (altFields.monthYear) {
        my = $(altFields.monthYear).val();
        //console.debug('my = ' + my);
      }

      // create date - d+m+y, d+my or new one
      if (d && m && y) {
        //console.debug('d.m.y = ' + d + '.' + m + '.' + y);
        defDate = new Date(y, m - 1, d);
      } else if (d && my) {
        //console.debug('d.my = ' + d + '.' + my);
        arr = my.split("-");
        m = arr[0];
        y = arr[1];
        //console.debug('d.m.y = ' + d + '.' + m + '.' + y);
        defDate = new Date(y, m - 1, d);
      } else {
        //console.debug('default date');
        defDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + interval);
      }

      //console.debug(defDate);
      return defDate;
    }

    /**
     * Main loop
     */
    return this.each(function(){

      // get default dates
      if ($(this).hasClass('first')) {
        defDate = getDefaultDate(options.startAlt, 7);
      } else {
        defDate = getDefaultDate(options.endAlt, 14);
      }
      //console.debug('defDate = ' + defDate);

      // bind datepicker
      $(this).datepicker({
        dateFormat: options.dateFormat,
        maxDate: options.maxDate,
        onSelect: onSelect
      });

      // set default dates
      $(this).datepicker('setDate', defDate);
      if ($(this).hasClass('first')) {
        setAltFields(startAltInputs, defDate);
        startDate = defDate;
        // create correct end min date
        minEndDate = new Date(defDate.getFullYear(), defDate.getMonth(), defDate.getDate() + options.range);
      } else {
        endDate = defDate;
        setAltFields(endAltInputs, defDate);
      }

      // set min dates
      $(this).datepicker('option', 'minDate', $(this).hasClass('first') ? minStartDate : minEndDate);
    });
  };
})(jQuery);
