import Component from 'ember-component';
import computed from 'ember-computed';
import moment from 'moment';
import nTimes from 'web-client/utilities/times';
import run, { cancel } from 'ember-runloop';

export default Component.extend({
  hasFocus: false,
  didPick: false,
  value: null,
  isShowingList: false,
  didShowList: false,
  ignoreNextFocusOut: false,
  time: null,
  scrollToActiveItemTask: null,
  activeItemClass: 'balloon__link--active',

  // injected action
  onChange() {},

  didReceiveAttrs() {
    let time = moment(this.get('time'));

    if (time.isValid()) {
      this.set('value', time.format('h:mma'));
    }
  },

  pickableTimes: computed(function() {
    return generateTimes();
  }),

  focusIn() {
    this.showList();
  },

  focusOut() {
    if (this.ignoreNextFocusOut) {
      this.ignoreNextFocusOut = false;
    } else {
      this.set('isShowingList', false);
    }
  },

  notifyChange() {
    let time = this.$('input').val();
    this.set('value', time);
    this.get('onChange')(time);
  },

  showList() {
    // The first time we show the list we'll scroll the active item into view.
    // After that we'll just let the browser naturally preserved the scroll
    // position.
    if (!this.didShowList) {
      this.scrollToActiveItemTask = run.schedule('afterRender', this, this.scrollToActiveItem);
      this.didShowList = true;
    }

    this.set('isShowingList', true);
  },

  parseTime() {
    let value = this.$('input').val();
    let date = convertTimeStringToMoment(value);
    let dateString = date.isValid() ? date.format('h:mma') : '';
    this.$('input').val(dateString);
  },

  scrollToActiveItem() {
    let activeItem = this.$(`.${this.activeItemClass}`);

    // Scroll the active item into view so that it is in the middle of the picker.
    if (activeItem.length) {
      activeItem[0].scrollIntoView();

      let scrollContainer = activeItem.scrollParent();
      let offsetToCenter = (scrollContainer.outerHeight() - activeItem.outerHeight()) / 2;
      scrollContainer.scrollTop(
        scrollContainer.scrollTop() - offsetToCenter + activeItem.position().top
      );
    }
  },

  willDestroy() {
    this._super(...arguments);
    cancel(this.scrollToActiveItemTask);
  },

  actions: {
    pickTime(time) {
      this.$('input').val(time);
      this.notifyChange();
      this.$('input').focus();
      this.set('isShowingList', false);
    },

    onInputClick() {
      this.showList();
    },

    itemMouseDown() {
      this.ignoreNextFocusOut = true;
    },

    onChange() {
      this.parseTime();
      this.notifyChange();
    },

    onInput() {
      this.set('isShowingList', false);
    }
  }
});

export function convertTimeStringToMoment(timeString) {
  return moment(timeString, ['h:mma', 'h', 'h:mm', 'ha']);
}

function generateTimes() {
  let times = [];
  let meridiums = ['am', 'pm'];
  let hours = nTimes(12, (i) => i || 12);
  let minutes = ['00', '30'];

  meridiums.forEach((meridium) => {
    hours.forEach((hour) => {
      minutes.forEach((minute) => {
        times.push(`${hour}:${minute}${meridium}`);
      });
    });
  });

  return times;
}
