/* globals Twitch, i18n, _ */

import Ember from 'ember';
import Component from 'ember-component';
import run from 'ember-runloop';
import PanelModel from 'web-client/models/panel';
import computed from 'ember-computed';
import injectService from 'ember-service/inject';

const { $, observer } = Ember;

export default Component.extend({
  tagName: 'div',
  layoutName: 'components/panels/list',

  api: injectService(),

  editMode: false,
  showEmptyMessage: false,

  offText: i18n('OFF'),
  onText: i18n('ON'),

  contentSorting: ['display_order'],
  sortedPanels: computed.sort('panels', 'contentSorting'),

  isChannelOwner: computed('panels.user', function () {
    return Twitch.user.login() === this.get('panels.user');
  }),

  hasPanels: computed.notEmpty('panels'),
  shouldShowEmptyMessage: computed('hasPanels', 'showEmptyMessage', 'editMode', function() {
    return !this.get('editMode') && !this.get('hasPanels') && this.get('showEmptyMessage');
  }),

  // editMode adds a fake panel (add panel button) that needs to have its layout set up.
  canSetMasonry: computed('hasPanels', 'editMode', function () {
    return this.get('hasPanels') || this.get('editMode');
  }),

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

    let panels = this.get('panels');
    if (panels) {
      this.get('panels').load();
    }

    // On low-width viewports, swapping to the Info tab will not toggle panels.isLoading
    // so we trigger a reload separately here
    run.scheduleOnce('afterRender', this, this.reloadMasonry);
  },

  didReceiveAttrs() {
    this.refreshPanelLayout();
  },

  _syncPanelsOnLoad: observer('panels.isLoading', function () {
    if (!this.get('panels.isLoading')) {
      run.scheduleOnce('afterRender', this, this.reloadMasonry);
    }
  }),

  saveOrder: function (displayOrders) {
    this.get('panels').forEach(function (panel) {
      if (panel.get('id')) {
        let displayOrder = displayOrders[panel.get('id')];
        panel.set('display_order', displayOrder);
        panel.set('rollbackData.display_order', displayOrder);
      }
    });
    // Turns the mapping of ids => display_order into a sorted list of ids
    let displayOrderIds = _.chain(displayOrders).invert().pairs().pluck('1').value();
    this.get('api').request('post', `/api/channels/${this.get('panels.user')}/panels/order`, {ids: displayOrderIds});
  },

  _setSortable() {
    if (this.get('isSortableSet') || !this.get('hasPanels')) {
      return;
    }

    let self = this;

    $('.js-panels-contain').sortable({
      items: '.panel[data-id]',
      opacity: 1,
      containment: $('.js-panels'),
      tolerance: 'pointer',
      update: function () {
        let displayOrders = {};
        $(this).find('.panel[data-id]').each(function (index) {
          displayOrders[$(this).data('id')] = index + 1;
        });
        self.saveOrder(displayOrders);
      }
    });
    this.set('isSortableSet', true);
  },

  _destroySortable() {
    if (!this.get('isSortableSet')) {
      return;
    }

    $('.js-panels-contain').sortable('destroy');
    this.set('isSortableSet', false);
  },

  // setting masonry options does not update the layout except the first time
  // or after a destroy. Use reload to update layout without destroying.
  _setMasonry() {
    if (this.get('isMasonrySet') || !this.get('canSetMasonry')) {
      return;
    }

    $('.js-panels').masonry({
      itemSelector: '.panel',
      gutterWidth: 0,
      isFitWidth: true
    });

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

  // Must be called in an afterRender schedule or in didRender,
  // otherwise this method can cause flickering between renders
  reloadMasonry() {
    if (!this.get('canSetMasonry')) {
      return;
    }

    if (!this.get('isMasonrySet')) {
      this._setMasonry();
    }

    let $panels = $('.js-panels');
    let self = this;

    $panels.masonry('reload');

    // Images can change panel height and width on load -- refresh the layout
    $panels.imagesLoaded(function () {
      if (self.isDestroyed) {
        return;
      }

      if (self.get('isMasonrySet')) {
        this.masonry('reload');
      }
    });
  },

  _destroyMasonry() {
    if (!this.get('isMasonrySet')) {
      return;
    }

    $('.js-panels').masonry('destroy');
    this.set('isMasonrySet', false);
  },

  refreshPanelLayout() {
    let editMode = this.get('editMode');
    run.schedule('afterRender', this, this.reloadMasonry);

    if (editMode) {
      // Destroy masonry so its absolute layout positioning doesn't break sortable
      run.schedule('afterRender', this, this._destroyMasonry);
      this._setSortable();
    } else {
      this._destroySortable();
    }
  },

  actions: {
    refreshPanelLayout: function() {
      this.refreshPanelLayout();
    },

    toggleEditMode: function () {
      this.toggleProperty('editMode');
      this.refreshPanelLayout();
    },

    newPanel: function () {
      let panel = PanelModel.create({
        channel: this.get('panels.user'),
        display_order: this.get('panels.content.length') + 1,
        data: {title: '', image: '', link: ''}
      }, true);
      let isExtensionsEnabled = this.get('isExtensionsEnabled');
      let teespring = this.get('teespringCampaignEnabled');
      let isAny = this.get('panels.content').isAny('kind', 'teespring');
      let showPanelKindSelection = isExtensionsEnabled || (teespring && !isAny);
      panel.set('kind', showPanelKindSelection ? null : 'default');
      panel.set('rollbackData', panel.get('data'));
      this.get('panels').addObject(panel);
      this.refreshPanelLayout();
    },

    destroyPanel: function (panel) {
      if (panel.get('content._id')) {
        this.get('api').request('del', `/api/channels/${this.get('panels.user')}/panels/${panel.get('content._id')}`);
      }
      this.get('panels.content').removeObject(panel.get('content'));
    }
  }
});
