/* globals console, Krux, Twitch, _ */
import Ember from 'ember';
import Mixin from 'ember-metal/mixin';
import on from 'ember-evented/on';
import run from 'ember-runloop';
import getOwner from 'ember-owner/get';
import injectService from 'ember-service/inject';
import RSVP from 'rsvp';
import ContextBoundTasksMixin from 'web-client/mixins/context-bound-tasks';

const { Logger } = Ember;

export default Mixin.create(ContextBoundTasksMixin, {
  referrer: document.referrer,

  isFirstTransition: true,

  tracking: injectService(),
  recsHoldout: injectService('recs-holdout'),

  trackPageView: on('didTransition', function () {
    let referrer = this._referrer;

    this.runTask(() => {

      this._referrer = document.location.toString();

      let activeRouteHandlers = this._getActiveRouteHandlers(),
          activeRouteHandler  = activeRouteHandlers[activeRouteHandlers.length - 1],
          locationInfo        = this._getActiveLocationInfo(),
          trackPageViewInfo   = this._getActiveTrackPageViewInfo(),
          medium              = this._getActiveMedium();

      /** This console.debug stuff is useful.  Please don't remove. */

      /* eslint-disable no-console */
      if (Twitch.tracking.funnel.debugEnabled()) {
        console.group('Ember pageview debug output - route is', JSON.stringify(activeRouteHandler.routeName));
        console.log('location is', JSON.stringify(locationInfo.value),
          locationInfo.inherited ? `inherited from route ${JSON.stringify(locationInfo.routeName)}` :
          `defined in ${JSON.stringify(locationInfo.routeName)}`);
        console.log('trackPageView is', trackPageViewInfo.inherited ?
          `inherited from route ${JSON.stringify(trackPageViewInfo.routeName)}` :
          `defined in ${JSON.stringify(activeRouteHandler.routeName)}`);
        console.groupEnd();
      }
      /* eslint-enable no-console */

      let layoutContainer = getOwner(this).lookup('service:layout');

      // Git shorthash, for readability.
      let gitShortHash = window.EmberENV.GIT_VERSION && window.EmberENV.GIT_VERSION.slice(0, 7);

      // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
      let properties = {
        referrer:       referrer,
        location:       locationInfo.value,
        collapse_left:  layoutContainer ? layoutContainer.get('isLeftColumnClosed') : undefined,
        collapse_right: layoutContainer ? layoutContainer.get('isRightColumnClosed') : undefined,
        app_version:    gitShortHash,
        medium:         medium ? medium.value : undefined
      };
      // jscs:enable requireCamelCaseOrUpperCaseIdentifiers

      trackPageViewInfo.route.trackPageView.call(trackPageViewInfo.route, properties);

      this._setKrux();

      if (!this.isFirstTransition) {
        this.trigger('didTransition.postLaunch');
      }

      this.isFirstTransition = false;

      this.get('recsHoldout').trackRecsHoldout();
    });
  }),

  // Always end the current benchmark session when we transition out of a page.
  //
  // For details on benchmarking, see the following spec:
  // https://docs.google.com/document/d/1ATyyu-tj3ssCUQWD2vPd20l-AqdCwPMaUg74zJYcZXs/edit#heading=h.nchvwxmcebpk
  endBenchmarkingSession: on('willTransition', function () {
    // Ensure the benchmark library is loaded
    let benchmark = this.get('tracking.benchmark');
    if (benchmark) {

      // Unfortunately, the 'willTransition' event is fired when the page is initially loaded.
      // We don't want to end the benchmarking session that was begun in `benchmark/main.js` so
      // we ignore the first time that this event is triggered.
      if (benchmark._firstPageLoad) {
        benchmark._firstPageLoad = false;
      } else {
        benchmark.end();
      }
    }
  }),

  /** Helper Functions */

  _sendComscoreOnTransition: on('didTransition.postLaunch', function () {
    // Send comscore beacon on page transition from Ember -> Ember pages
    Twitch.tracking.sendComscoreBeacon({
      c1: 2,
      c2: 6745306,
      c3: 1,
      c5: "01"
    });
  }),

  _notifySentinel: on('didTransition.postLaunch', function () {
    // Notify Sentinel on page transition from Ember -> Ember pages
    Twitch.sentinel.pageTransition();
  }),

  _getActiveLocationInfo() {
    /** ttLocation is the location parameter sent when tracking pageview.
        The active route defines or inherits ttLocation from the active route chain back to application route. */
    return this._getActivePropertyInfo('ttLocation');
  },

  _getActiveTrackPageViewInfo() {
    /** trackPageView is the hook that gets called to track pageview.
        The active route defines or inherits trackPageView from the active route chain back to application route. */
    return this._getActivePropertyInfo('trackPageView');
  },

  _getActiveRouteHandlers() {
    return _.map(this.router.currentHandlerInfos, function (handlerInfos) { return handlerInfos.handler; });
  },

  _getActiveMedium() {
    /** medium is the location where the user is coming from.
    The active route defines or inherits ttLocation from the active route chain back to application route. */
    return this._getActivePropertyInfo('medium');
  },

  _getActivePropertyInfo(propertyName) {
    let activeRouteHandlers = this._getActiveRouteHandlers(),
        activeRouteHandler = activeRouteHandlers[activeRouteHandlers.length - 1],
        propertyValue,
        routeWhichDefinesProperty;
    activeRouteHandlers.forEach(function (routeHandler) {
      if (propertyName in routeHandler || routeWhichDefinesProperty === undefined) {
        routeWhichDefinesProperty = routeHandler;
        propertyValue = routeHandler[propertyName];
      }
    });
    return {
      value: propertyValue,
      route: routeWhichDefinesProperty,
      routeName: routeWhichDefinesProperty.routeName,
      inherited: routeWhichDefinesProperty !== activeRouteHandler
    };
  },

  _kruxAjaxMod() {
    Krux('page:load', function (err) {
      if (err !== null) {
        Logger.error("Krux did not load properly: ", err);
      }
    }, {pageView: true});
  },

  _setKuid() {
    let kuid = Krux.user;
    if (kuid) {
      Twitch.asyncAds.metadata.kuid = kuid;
    }
  },

  _setKrux() {
    return new RSVP.Promise((resolve, reject) => {
      let startTime = new Date();

      let checkForKrux = () => {
        if (this.isDestroyed) {
          run(null, reject);
          return;
        }

        if (typeof Krux === 'undefined') {
          if ((new Date()) - startTime > 5000) {
            run(null, reject);
          } else {
            setTimeout(checkForKrux, 100);
          }
        } else {
          run(null, resolve);
        }
      };
      checkForKrux();
    }, 'TrackingRouterMixin#_setKrux').then(() => {
      this._kruxAjaxMod();
      this._setKuid();
    });
  }
});
