/* globals Twitch */

import $ from 'jquery';
import Route from 'ember-route';
import ChannelModel from 'web-client/models/deprecated-channel';
import DeprecatedVideo from 'web-client/models/deprecated-video';
import ContextBoundTasksMixin from 'web-client/mixins/context-bound-tasks';
import { CSGO, CREATIVE } from 'web-client/utilities/game-names';
import injectService from 'ember-service/inject';
import { assign as merge } from 'ember-platform';
import get from 'ember-metal/get';
import run from 'ember-runloop';
import Mousetrap from 'mousetrap';
import RSVP from 'rsvp';
import { ROUTES, routeMatches } from 'web-client/utilities/route-matcher';
import { normalizeVideoId } from 'web-client/utilities/normalize-video-id';

import VodCoviewsTrackingMixin from 'web-client/mixins/vod-coviews/tracking';
import CarouselTrackingMixin from 'web-client/mixins/carousel-tracking';

/**
 *  Require the following modules so that we ensure they get registered in App.__container__ before they get looked-up
 *  For more information about why we're doing this weird hack, see app/models/deprecated-video.js
 */
import 'web-client/models/video-manager-properties';

let MINI_PLAYER_ROUTES = [
  ROUTES.VIDEOS_PAGE,
  ROUTES.FOLLOWERS_PAGE,
  ROUTES.FOLLOWING_PAGE,
  ROUTES.FRIENDS_PAGE,
  ROUTES.DIRECTORY,
  ROUTES.CLIPS_PAGE,
  ROUTES.COMMUNITY_PAGE,
  ROUTES.COLLECTIONS_PAGE
];

const FULL_PLAYER_ROUTES = [
  ROUTES.CHANNEL_PAGE,
  ROUTES.VOD_PAGE
];

export default Route.extend(ContextBoundTasksMixin, VodCoviewsTrackingMixin, CarouselTrackingMixin, {
  ttLocation: undefined,
  similarChannels: injectService(),
  conversations: injectService('twitch-conversations/conversations'),
  layout: injectService(),
  persistentPlayer: injectService(),
  persistentPlayerContent: injectService(),
  experiments: injectService(),
  browse: injectService(),
  friends: injectService('twitch-friends-list/api'),
  vodChatService: injectService(),
  session: injectService(),
  globals: injectService(),
  feeds: injectService(),

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

    let session = this.get('session');
    let browse = this.get('browse');

    return RSVP.all([
      session.initializeSession(),
      browse.checkExperiment()
    ]);
  },

  trackPageView(properties) {
    Twitch.tracking.funnel.trackPageView(properties);
  },

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

    let layout = this.get('layout');

    // toggle left column
    Mousetrap.bind('alt+l', () => {
      if (!this.get('layout.isTooSmallForLeftColumn')) {
        run(this, 'send', 'handleLeftColumnToggleClick');
      }

      return false;
    });

    // toggle right column
    Mousetrap.bind('alt+r', () => {
      if (!this.get('layout.isTooSmallForRightColumn')) {
        run(this, 'send', 'handleRightColumnToggleClick');
      }

      return false;
    });

    // center the player
    Mousetrap.bind('alt+c', () => {
      try {
        let playerPos = $('.js-player').position();
        let playerTop = (playerPos.top - 20);
        $('#main_col .tse-scroll-content').stop().animate({scrollTop: playerTop}, 150, 'swing');
        return false;
      } catch (e) {
        // Swallow all errors :/
      }
    });

    // show and focus chat box
    Mousetrap.bind('alt+enter', () => {
      run(() => {
        if (layout.get('isRightColumnClosedByUserAction')) {
          this.send('handleRightColumnToggleClick');
        }
        layout.set('isChatOpenOnProfileSidebar', true);
      });

      this.runTask(() => {
        $('.js-chat-container .chat_text_input').focus();
      });
    });

    // hide the loading screen because the app has started
    $('.js-ember-loading-screen').hide();
  },

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

    Mousetrap.unbind('alt+enter');
    Mousetrap.unbind('alt+c');
    Mousetrap.unbind('alt+r');
    Mousetrap.unbind('alt+l');
  },

  model() {
    let { isAuthenticated } = this.get('session');

    let findSimilarChannels;
    let newsFeedEnabled;
    if (isAuthenticated) {
      newsFeedEnabled = this.get('feeds').hasNewsFeed().then(hasNewsFeed => {
        if (hasNewsFeed) {
          MINI_PLAYER_ROUTES.push(ROUTES.INDEX);
        }
      });

      this.get('friends').initializeFriendsList();

      // Values used by the navigation
      let similarChannels = this.get('similarChannels');
      findSimilarChannels = similarChannels.findRecommendations();
    } else {
      findSimilarChannels = RSVP.resolve();
      newsFeedEnabled = RSVP.resolve();
    }

    /*
     * This is intentionally a POJO. The route loading should not be blocked
     * on the findSimilarChannels promise. However the `directory/discovery`
     * route will fetch this and block.
     */
    return { findSimilarChannels, newsFeedEnabled };
  },

  buildPageTitle() {
    return {
      title: 'Twitch',
      hasTwitchTitleSuffix: false
    };
  },

  updatePersistentPlayer(transitionRoute) {
    if (routeMatches(transitionRoute, MINI_PLAYER_ROUTES) && this.get('persistentPlayer.shouldPersist')) {
      this.send('shrinkPlayer', 'minimize');
    } else if (!routeMatches(transitionRoute, FULL_PLAYER_ROUTES) || !this.get('persistentPlayer.shouldPersist')) {
      this.send('hidePlayer');
    }
  },

  actions: {
    // http://emberjs.com/guides/routing/loading-and-error-substates/
    loading() {
      // insert generic handler here

      // return true causes the base loading template to be rendered
      return true;
    },

    error() {
      // insert generic handler here

      // return true causes the base error template to be rendered
      return true;
    },

    openInModal(template, controller, options) {
      return this.render(template, merge({
        into: 'application',
        controller: controller,
        outlet: 'modal'
      }, options));
    },

    closeModal() {
      return this.disconnectOutlet({
        outlet: 'modal',
        parentView: 'application'
      });
    },

    handleLeftColumnToggleClick() {
      this.get('layout').toggleProperty('isLeftColumnClosedByUserAction');
    },

    handleRightColumnToggleClick() {
      this.get('layout').toggleProperty('isRightColumnClosedByUserAction');
      this.get('conversations').closeConversation();
      // If we have chat, let's disconnect if the user hides the right sidebar
      // This is a major perf boost if the user is only watching video
      let chatController = this.controllerFor('chat');
      if (chatController.currentRoom) {
        let action = this.get('layout.isRightColumnClosedByUserAction') ? 'hideChat' : 'show';
        chatController.send(action);
      }
    },

    handleProfileClick(user) {
      $('.tipsy').remove(); // hack to hide tooltips that will never close
      this.transitionTo('profile', ChannelModel.find({id: user ? get(user, 'name') : this.get('session.userData.login')}).load());
    },

    handleDashboardsClick() {
      this.transitionTo('dashboards.index', ChannelModel.find({id: this.get('session.userData.login')}).load());
    },

    handleVideoManagerClick() {
      this.transitionTo('manager.past-broadcasts', ChannelModel.find({id: this.get('session.userData.login')}).load());
    },

    handleCommunitiesFilterClick() {
      this.transitionTo('directory.communities');
    },

    handleGamesFilterClick() {
      this.transitionTo('directory.games');
    },

    handleChannelsFilterClick() {
      this.transitionTo('directory.channels.all');
    },

    handleVideosFilterClick() {
      this.transitionTo('directory.videos.video-type', 'all');
    },

    handleFollowingFilterClick() {
      this.transitionTo('directory.following');
    },

    handleCreativeFilterClick() {
      this.transitionTo('directory.creative');
    },

    handleNotLoggedIn(options) {
      options = options || {};
      $.login(options);
    },

    handleLoginButtonClick() {
      $.login({mpSourceAction: 'login-button'});
    },

    handleSignupButtonClick() {
      $.signup({mpSourceAction: 'signup-button'});
    },

    handleLogoutButtonClick() {
      let {isAuthenticated, userData} = this.get('session');

      if (isAuthenticated) {
        let csrf = $("<input>").attr({
          type: "hidden",
          name: "authenticity_token",
          value: userData.csrf_token
        });
        $('#logout_form').append(csrf).submit();
      } else {
        $('#logout_form').submit();
      }
    },

    handleStreamClick(channel, index) {
      if (channel && channel._isCarousel) {
        this.trackCarouselStreamItemClick(channel, index);
      }
      this.transitionTo('channel.index', ChannelModel.find({id: channel ? channel.id || channel.channel.name : this.get('session.userData.login')}).load());
    },

    handleHostClick(host) {
      this.transitionTo('channel.index', ChannelModel.find({id: host.id}).load());
    },

    handleGameThumbnailClick(model) {
      $('.tipsy').remove(); // hack to hide tooltips that will never close
      let route;

      if (model.game === CSGO) {
        route = model instanceof DeprecatedVideo ? '.videos' : '.channels';
        this.transitionTo(`directory.csgo${route}`);
      } else if (model.game === CREATIVE) {
        if (model instanceof DeprecatedVideo) {
          return this.transitionTo('directory.creative.hashtag.videos', 'all');
        }
        this.transitionTo('directory.creative');
      } else {
        route = model instanceof DeprecatedVideo ? 'directory.game.videos' : 'directory.game';
        this.transitionTo(route, model.game);
      }
    },

    handleGameClick(game) {
      if (game.id === CSGO) {
        this.transitionTo('directory.csgo.channels');
      } else if (game.id === CREATIVE) {
        this.transitionTo('directory.creative');
      } else {
        this.transitionTo('directory.game', game.id);
      }
    },

    handleCommunityClick(community) {
      if (!community) {
        this.transitionTo('communities.create');
      } else {
        let name = (typeof community.name === 'string') ? community.name : community.get('name');
        this.transitionTo('communities.community', name);
      }
    },

    handlePromotedGameClick(game, location) {
      let properties = {
        'game': game.id,
        'location': location,
        'promoted': "true"
      };
      Twitch.tracking.mixpanel.setGameClickVars(properties);
      if (game.trackingUrls.clickthroughUrl) {
        window.location = game.trackingUrls.clickthroughUrl;
      } else {
        this.transitionTo('directory.game', game.id);
      }
    },

    handleVideoClick(video, index, total) {
      let videoId = normalizeVideoId(video.id);
      let visitedVods = Twitch.storage.getObject('visitedVods') || {};

      visitedVods[videoId] = true;
      Twitch.storage.setObject('visitedVods', visitedVods);

      if (video.isRecommended) {
        this.trackCoviewClick(video, index, total);
      }

      if (video._isCarousel) {
        this.trackCarouselVideoItemClick(video, index);
      }

      if (video.isPlayerRecommendation) {
        Twitch.tracking.funnel.addProperties({
          medium: 'video-player',
          content: video.playerRecommendationType
        });
      }

      const currentCollection = this.get('persistentPlayerContent.currentCollection');
      const queryObj = (currentCollection && video.preserveCollection) ? {collection: currentCollection} : {};

      this.transitionTo('videos', videoId, {queryParams: queryObj});
    },

    handleBackpackClick() {
      this.transitionTo('backpack');
    },

    willTransition(transition) {
      this.send('closeModal');
      this.updatePersistentPlayer(transition.targetName);
      this._super(...arguments);
    },

    didTransition() {
      this.runTask(() => {
        window.prerenderReady = true;
      }, 500);
      this._super(...arguments);
    },

    showPlayer() {
      this.set('persistentPlayer.shouldShow', true);
    },

    hidePlayer() {
      this.set('persistentPlayer.shouldShow', false);
    },

    hideMiniPlayer() {
      if (this.get('persistentPlayer.isMini')) {
        this.send('hidePlayer');
      }
    },

    shrinkPlayer(reason) {
      let player = this.get('persistentPlayer');

      if (this.get('layout.isTheatreMode')) {
        this.set('layout.isTheatreMode', false);
        player.setMini(true);
      } else {
        player.shrink(reason);
      }
    },

    anchorPlayer(reason) {
      let player = this.get('persistentPlayer');
      player.anchor(reason);
    },

    setPlayerStream(channelModel) {
      this.set('persistentPlayerContent.currentChannel', channelModel);
      this.set('persistentPlayerContent.currentVOD', null);
    },

    setPlayerVOD(vodModel) {
      this.set('persistentPlayerContent.currentVOD', vodModel);
      this.store.findRecord('channel', vodModel.get('channel.id')).then(channel => {
        this.set('persistentPlayerContent.currentChannel', channel);
      });
    },

    setCollection(collection) {
      this.set('persistentPlayerContent.currentCollection', collection);
    },

    returnToPlayerRoute(route, params) {
      this.transitionTo(route, params);
    }
  }
});
