/* globals Twitch, _, i18n */

import on from 'ember-evented/on';
import $ from 'jquery';
import EmberObject from 'ember-object';
import Component from 'ember-component';
import run from 'ember-runloop';
import DeprecatedVideo from 'web-client/models/deprecated-video';
import injectController from 'web-client/utilities/inject-controller';
import injectService from 'ember-service/inject';
import computed from 'ember-computed';
import observer from 'ember-metal/observer';
import { normalizeVideoId } from 'web-client/utilities/normalize-video-id';

export default Component.extend({
  globals: injectService(),
  playlistMoreInfo: computed.alias('globals.playlistMoreInfo'),

  layout: injectService(),
  managerController: injectController('manager'),
  store: injectService(),

  videoLengths: computed.mapBy("playlistVideos", "video.length"),
  playlist: computed.alias('playlistChannel.playlists.firstObject'),
  playlistDuration: computed.sum("videoLengths"),
  playlistVideos: [],
  sortedVideos: [],

  /*
  This next observer and the didRender function are a specific workaround for
  bad interaction between Ember's DOM management and JQueryUI's. When JQueryUI
  influences the DOM, Ember sort of gets confused about it and the only way to
  reliably get Ember into a sane state is to blow away the DOM elements entirely
  and let Ember rebuild them.
  */
  sortedVideosHelper: observer("playlistVideos", function() {
    this.set('sortedVideos', []);
  }),

  didRender: function() {
    if (this.get('sortedVideos').length !== this.get('playlistVideos').length) {
      let videos = this.get('playlistVideos').sortBy('idx');
      this.set('sortedVideos', videos);
    }
  },

  // Passed in OfflinePlaylistChannel.id
  model: null,
  playlistChannel: null,
  isLoadingPlaylist: true,

  _fetchOfflinePlaylistChannel: on('didInsertElement', function() {
    let id = this.get('model');

    this.set('isLoadingPlaylist', true);

    this.get('store').find('offline-playlist-channel', id).then(playlistChannel => {
      this.set('playlistChannel', playlistChannel);
      run.scheduleOnce('afterRender', this, 'setupListeners');
    }).finally(() => {
      this.set('isLoadingPlaylist', false);
    });
  }),

  // playlistVideos is our denormalized array which holds video objects
  // video objects include their index (for sorting purposes), a randomId (because they need not be unique) and a store.js VideoModel
  createPlaylistVideos: observer('playlistChannel', 'isLoadingPlaylist', function() {
    let model = this.get('playlistChannel');
    if (model && model.get('isLoaded')) {
      let vodIds = this.get('playlist.vodIds');

      if (vodIds) {
        let playlistVideos = vodIds.map(function (id, idx) {
          return EmberObject.create({
            idx: idx,
            randomId: Math.random(),
            video: DeprecatedVideo.findOne(`v${id}`).load()
          });
        });
        this.set('playlistVideos', playlistVideos);
      }
    }
  }),

  updatePlaylist() {
    // Turn playlistVideos to vodIds; then save
    let playlistVideos = this.get('playlistVideos'),
        playlist = this.get('playlist') || this.get('store').createRecord('offline-playlist', {
          version: 1,
          channel: this.get('playlistChannel')
        });

    let vodIds = _.sortBy(playlistVideos, (video) => video.idx).map(video => normalizeVideoId(video.video.id));
    playlist.set('vodIds', vodIds);
    playlist.save().catch(() => {
      Twitch.notify.error(i18n("Your playlist failed to update"));
    });
  },

  // Runs after fetching data and rendering. See invocation in _fetchOfflinePlaylistChannel.
  setupListeners() {
    this._initScroller();
    this._initLastScrollPosition();
    this._initWhatisthis();
    this._initPlaylistInitMessage();
  },

  destroyListeners: on('willDestroyElement', function() {
    if (this.$('#right_col .scroll').data('plugin_TrackpadScrollEmulator')) {
      this.$('#right_col .scroll').TrackpadScrollEmulator('destroy');
    }
    this.$('.playlist-toggle .switch').off(`click.${this.elementId}`);

    let $tooltipDismissButton = this.$('.playlist-container .js-what-tooltip .js-dismiss');
    $tooltipDismissButton.off(`click.${this.elementId}`);
  }),

  _initScroller() {
    this.$('#right_col .scroll').TrackpadScrollEmulator({
      wrapContent: false,
      scrollbarHideStrategy: 'rightAndBottom'
    });
  },

  _initLastScrollPosition() {
    let curScrollpos = parseInt($('.manager').attr('data-playlistscroll'));

    if (curScrollpos > 0) {
      let currentScroll = curScrollpos + this.$('.playlist-item').outerHeight();
      this.$('.playlist-container .tse-scroll-content').scrollTop(currentScroll);
    }
  },

  _initWhatisthis() {
    let TOOLTIP_DISMISSED_FLAG  = 'Twitch.manager.playlistTooltipDismissed',
        $tooltip = this.$('.playlist-container .js-what-tooltip'),
        $tooltipDismissButton = $tooltip.find('.js-dismiss');

    $tooltipDismissButton.on(`click.${this.elementId}`, function () {
      Twitch.storage.setObject(TOOLTIP_DISMISSED_FLAG, true);
      $tooltip.addClass('hidden');
    });

    if (Twitch.storage.getObject(TOOLTIP_DISMISSED_FLAG) !== true) {
      $tooltip.removeClass('hidden');
    }
  },

  _initPlaylistInitMessage() {
    this.$('.playlist-toggle .switch').on(`click.${this.elementId}`, () => {
      if (!this.get('playlistChannel.enabled')) {
        this.$('.sticky-message').slideDown(160);
      }
    });
  },

  disableSort: observer('playlistChannel.enabled', function () {
    if (this.get('playlistChannel.enabled')) {
      $('.playlist-container .zone-container').sortable('disable');
    }
  }),

  enableSort: observer('playlistChannel.enabled', function () {
    if (!this.get('playlistChannel.enabled')) {
      $('.playlist-container .zone-container').sortable('enable');
    }
  }),

  actions: {
    toggleStopModal() {
      this.toggleProperty('isShowingStopModal');
    },

    toggleClearModal() {
      this.toggleProperty('isShowingClearModal');
    },

    onClearPlaylist() {
      this.set('playlistVideos', []);
    },

    initEnabled() {
      if (this.get('playlistChannel.enabled')) {
        $('.playlist-container .zone-container').sortable('disable');
      }
    },

    close() {
      $('.sticky-message').hide();
    },

    addVideo(videoId, randomId, indexes) {
      videoId = normalizeVideoId(videoId);
      let vod = this.get('store').findRecord('video', videoId);

      vod.then(video => {
        let newVideo = EmberObject.create({idx: indexes[randomId], randomId, video});
        if (this.get('playlistVideos') === undefined) {
          this.set('playlistVideos', []);
        }
        this.get('playlistVideos').pushObject(newVideo);
        this.send('updateSortOrder', indexes);
      });
    },

    removeVideo(video) {
      let index = video.get('idx'),
          model = this.get('playlistVideos');

      // When we remove an object we want to reset the indexes to the correct value.
      _.each(model, function (v) {
        if (v.get('idx') > index) {
          v.set('idx', v.get('idx') - 1);
        }
      });
      model.removeObject(video);
      this.updatePlaylist();
    },

    updateSortOrder(indexes) {
      _.each(this.get('playlistVideos'), function (video) {
        let index = indexes[video.get('randomId')];
        video.set('idx', index);
      });
      this.updatePlaylist();
    },

    clearPlaylist() {
      let channel = this.get('playlistChannel');
      if (this.get('sortedVideos.length') && !channel.get('enabled')) {
        this.send('toggleClearModal');
      }
    },

    toggleEnabled() {
      let channel = this.get('playlistChannel');

      if (channel.get('enabled')) {
        this.send('toggleStopModal');
      } else {
        channel.set('enabled', true);
        channel.save().catch(() => {
          Twitch.notify.error(i18n("Your playlist failed to update"));
        });
      }
    }
  }
});
