import Component from 'ember-component';
import computed from 'ember-computed';
import observer from 'ember-metal/observer';
import run from 'ember-runloop';
import $ from 'jquery';
import moment from 'moment';

import { WEEKS_RESOLUTION, WEEK_FORMAT } from 'web-client/components/dashboards/revenue/date-picker/component';

export default Component.extend({
  classNames: ['flex__item'],

  // Passed in properties:
  momentStartDate: null,
  momentEndDate: null,
  isDatepickerDisabled: null,
  updateDateFilter: null,

  // Own properties:
  weekDifference: computed('momentStartDate', 'momentEndDate', function () {
    return this.get('momentEndDate').diff(this.get('momentStartDate'), WEEKS_RESOLUTION) + 1;
  }),

  didInsertElement() {
    this._super(...arguments);

    let momentStartDate = this.get('momentStartDate');
    let momentEndDate = moment.min(this.get('momentEndDate'), moment().endOf('day'));

    this.set('momentEndDate', momentEndDate);

    this.$datepickerStart = this.$().find('input.js-datepicker-start');
    this.$datepickerEnd = this.$().find('input.js-datepicker-end');

    this.$datepickerStart.val(momentStartDate.format(WEEK_FORMAT));
    this.$datepickerEnd.val(momentEndDate.format(WEEK_FORMAT));

    this.$(document).on('mousemove', '.ui-datepicker-calendar tr', function () {
      if (this.isDestroyed) {
        return;
      }

      run(() => {
        $(this).find('td a').addClass('ui-state-hover');
      });
    });

    this.$(document).on('mouseleave', '.ui-datepicker-calendar tr', function () {
      if (this.isDestroyed) {
        return;
      }

      run(() => {
        $(this).find('td a').removeClass('ui-state-hover');
      });
    });

    this._setDatepickerStartByWeek();
    this._setDatepickerEndByWeek();

    let updateDateObject = {
      startDate: momentStartDate,
      endDate: momentEndDate,
      resolution: WEEKS_RESOLUTION
    };

    run.once(this, 'updateDateFilter', updateDateObject);
  },

  willDestroyElement() {
    this._super(...arguments);

    this.$datepickerStart.datepicker('destroy');
    this.$datepickerEnd.datepicker('destroy');

    $(document).off('mousemove', '.ui-datepicker-calendar tr');
    $(document).off('mouseleave', '.ui-datepicker-calendar tr');
  },

  updateStartAndEndWeeks: observer('momentStartDate', 'momentEndDate', function () {
    let momentStartDate = this.get('momentStartDate');
    let momentEndDate = this.get('momentEndDate');

    let updateDateObject = {
      startDate: momentStartDate,
      endDate: momentEndDate,
      resolution: WEEKS_RESOLUTION
    };

    run.once(this, 'updateDateFilter', updateDateObject);
  }),

  _setDatepickerStartByWeek() {
    let startOfWeek = this.get('momentStartDate').startOf('week');

    this.set('momentStartDate', startOfWeek);
    this._formatDatepickerInputValueByWeek(startOfWeek, this.$datepickerStart);

    this.$datepickerStart.datepicker({
      beforeShowDay: (dateToShow) => {
        let endOfWeekDate = moment(this.get('momentStartDate')).endOf('week');
        let isBetween = moment(dateToShow).isBetween(this.get('momentStartDate'), endOfWeekDate, null, '[]');
        let cssClass = isBetween ? 'ui-datepicker-current-day': '';

        return [true, cssClass];
      },
      dateFormat: WEEK_FORMAT,
      defaultDate: this.get('momentStartDate').toDate(),
      maxDate: this.get('momentEndDate').toDate(),
      nextText: '',
      onClose() {
        $(this).blur();
      },
      onSelect: (formattedDateString) => {
        let newMomentStartDate = moment(formattedDateString, WEEK_FORMAT).startOf('week');

        this.set('momentStartDate', newMomentStartDate);
        this.$datepickerStart.datepicker('setDate', newMomentStartDate.toDate());

        this._formatDatepickerInputValueByWeek(this.get('momentStartDate'), this.$datepickerStart);
      },
      prevText: '',
      selectOtherMonths: true,
      showOtherMonths: true
    });
  },

  _setDatepickerEndByWeek() {
    let oldMomentEndDate = this.get('momentEndDate');
    let startOfWeek = moment(oldMomentEndDate).startOf('week');
    let endOfWeek = moment(oldMomentEndDate).endOf('week');

    this.set('momentEndDate', moment.min(endOfWeek, moment().endOf('day')));
    this._formatDatepickerInputValueByWeek(startOfWeek, this.$datepickerEnd);

    this.$datepickerEnd.datepicker({
      beforeShowDay: (dateToShow) => {
        let startOfWeekDate = moment(this.get('momentEndDate')).startOf('week');
        let isBetween = moment(dateToShow).isBetween(startOfWeekDate, this.get('momentEndDate'), null, '[]');
        let cssClass = isBetween ? 'ui-datepicker-current-day': '';

        return [true, cssClass];
      },
      dateFormat: WEEK_FORMAT,
      defaultDate: this.get('momentEndDate').toDate(),
      maxDate: moment.max(moment(this.get('momentEndDate')).startOf('week'), moment().endOf('day')).toDate(),
      nextText: '',
      onClose() {
        $(this).blur();
      },
      onSelect: (formattedDateString) => {
        let newMomentEndDate = moment.min(moment().endOf('day'), moment(formattedDateString, WEEK_FORMAT).endOf('week'));
        let newMomentStartOfEndDate = moment(formattedDateString, WEEK_FORMAT).startOf('week');

        this.set('momentEndDate', newMomentEndDate);

        this.$datepickerEnd.datepicker('setDate', newMomentStartOfEndDate.toDate());
        this._formatDatepickerInputValueByWeek(newMomentStartOfEndDate, this.$datepickerEnd);
        this.$datepickerStart.datepicker('option', 'maxDate', newMomentEndDate.toDate());

        if (newMomentStartOfEndDate.isBefore(this.get('momentStartDate'))) {
          this.set('momentStartDate', newMomentStartOfEndDate);
          this.$datepickerStart.datepicker('setDate', newMomentStartOfEndDate.toDate());
        }

        this._formatDatepickerInputValueByWeek(this.get('momentStartDate'), this.$datepickerStart);
      },
      prevText: '',
      selectOtherMonths: true,
      showOtherMonths: true
    });
  },

  _formatDatepickerInputValueByWeek(momentDateStartOfWeek, $datepicker) {
    let startDateOfWeek = momentDateStartOfWeek.format(WEEK_FORMAT);
    let endDateOfWeek = moment.min(moment(momentDateStartOfWeek).endOf('week'), moment().endOf('day')).format(WEEK_FORMAT);
    let formattedInputValue = `${ startDateOfWeek } - ${ endDateOfWeek }`;

    $datepicker.val(formattedInputValue);
  }
});
