/* global Twitch */
import Component from 'ember-component';
import computed from 'ember-computed';
import injectService from 'ember-service/inject';
import $ from 'jquery';
import run from 'ember-runloop';
import config from 'web-client/config/environment';

export default Component.extend({
  session: injectService(),
  bits: injectService(),
  bitsRoom: injectService(),
  tracking: injectService(),
  playerRemoteControl: injectService(),
  layout: injectService(),

  classNames: ['js-bits-watch-ad-cta'],
  classNameBindings: ['watchAnother:bits-footer__button-wrapper:bits-purchase__row'],
  minimumBits: 5,
  isAdModalOpen: false,
  hasAdDimensions: false,
  modalWidth: '',
  modalHeight: '',
  watchedAd: false,
  isEntitling: false,
  adblockError: false,
  genericError: false,
  watchAnother: false,
  limitReachedError: false,
  adRewardAmount: 0,
  disableWatchAd: false,
  channelName: computed.readOnly('bitsRoom.channelName'),
  channelId: computed.readOnly('bitsRoom.channelId'),

  init() {
    this._super(...arguments);
    this._calcBitsAvailability();
  },

  willDestroyElement() {
    this._super(...arguments);
    $(window).off('.ad-modal');
  },

  actions: {
    openAdModal(actionName) {
      if (this.get('disableWatchAd')) { return; }

      this.get('bits').loadBalance(this.get('channelId')).then((response) => {
        if (this.isDestroyed) { return; }
        this.get('tracking').trackBitsCardInteractions(actionName, this.get('session.userData.login'), response.balance);
      });

      this._attachModalCallbacks();
      this.set('isAdModalOpen', true);
      this.set('modalWidth', `990px`);
      this.set('modalHeight', `540px`);
      this.set('hasAdDimensions', true);
      this.get('playerRemoteControl').mute();
      this.set('layout.showWormholeOverlay', true);
    },
    closeAdModal() {
      this._closeAdModal();
    }
  },

  _calcBitsAvailability() {
    if (config.environment !== 'test') {
      this.get('bits').bitsAdsAvailable(this.get('session.userData.id')).then(response => {
        if (this.isDestroyed) { return; }

        if (!response || response.error) {
          this.set('disableWatchAd', true);
          this._trackBitsAdsAvailability(false);
          return;
        }

        this.set('disableWatchAd', false);
        this._trackBitsAdsAvailability(true);
      });
    }
  },

  _attachModalCallbacks() {
    $(window).bind('message.ad-modal', (evt) => {
      let origEvt = evt.originalEvent;
      if (origEvt.origin !== window.location.origin) {
        return;
      }

      let data = origEvt.data;
      if (typeof data !== 'object' || !data.msgSrc || data.msgSrc !== 'trueXAd') {
        return;
      }

      run(() => {
        this._handleModalMsg(data);
      });
    });
  },

  _closeAdModal() {
    $(window).off('.ad-modal');
    this.set('hasAdDimensions', false);
    this.set('isAdModalOpen', false);
    this.get('playerRemoteControl').unmute();
    this.set('layout.showWormholeOverlay', false);

    if (this.get('watchedAd')) {
      // if the entitle promise hasn't completed, the callbacks of that promise will handle the result
      if (!this.get('isEntitling')) {
        if (this.get('genericError')) {
          this.get('bitsRoom').showAdUnknownError();
        } else {
          this.get('bitsRoom').showAdReward(this.get('adRewardAmount'));
        }
      }
    } else {
      if (this.get('adblockError')) {
        this.get('bitsRoom').showAdErrorAdblock();
      } else if (this.get('genericError')) {
        this.get('bitsRoom').showAdUnknownError();
      } else if (this.get('limitReachedError')) {
        this.get('bitsRoom').showAdLimitReached();
      } else {
        this.get('bitsRoom').showAdExitedEarly();

        let currentActivity = this.get('currentActivity');
        let currentRequestId = this.get('currentRequestId');

        if (currentActivity && currentRequestId) {
          this._trackEvent('bits_ads_impression_dismissed', currentRequestId, {
            campaign_id: currentActivity.campaign_id
          });
        }
      }
    }

    if (this.get('watchAnother')) {
      this._calcBitsAvailability();
    }
  },

  _handleModalMsg(data) {
    let requestId = data.requestId;

    switch (data.msgType) {
      case 'dimensions':
        this.set('modalWidth', `${data.width}px`);
        this.set('modalHeight', `${data.height}px`);
        this.set('hasAdDimensions', true);
        break;
      case 'requestAd': {
        let activity = data.activity ? JSON.parse(data.activity) : null;

        this._trackEvent('bits_ads_request', requestId, {
          location: 'channel',
          request_method: 'show_ad_button',
          channel: this.get('channelName'),
          ad_available: activity !== null,
          campaign_id: activity ? activity.campaign_id : null
        });
        break;
      }
      case 'onStart': {
        let activity = JSON.parse(data.activity);

        this.set('currentActivity', activity);
        this.set('currentRequestId', requestId);
        this._trackEvent('bits_ads_impression', requestId, {
          campaign_id: activity.campaign_id
        });
        break;
      }
      case 'onCredit': {
        let tuid = this.get('session.userData.id');
        let engagement = JSON.parse(data.engagement);
        let bitsSvc = this.get('bits');

        this.set('watchedAd', true);
        this.set('isEntitling', true);
        bitsSvc.entitleAdBits(`${tuid}`, engagement).then((response) => {
          if (this.isDestroyed) { return; }
          this.set('isEntitling', false);

          let bitsGranted = response.bits_granted;
          if (this.get('isAdModalOpen')) {
            this.set('adRewardAmount', bitsGranted);
          } else {
            this.get('bitsRoom').showAdReward(bitsGranted);
          }
        }, () => {
          if (this.isDestroyed) { return; }
          this.set('isEntitling', false);
          this.set('genericError', true);

          if (!this.get('isAdModalOpen')) {
            this.get('bitsRoom').showAdUnknownError();
          }
          this._trackEvent('bits_ads_entitlement_error', requestId, {
            channel: this.get('channelName')
          });
        });

        this._trackEvent('bits_ads_impression_complete', requestId, {
          campaign_id: engagement.ad.campaign_id
        });
        break;
      }
      case 'onFinish':
      case 'onClose':
        this._closeAdModal();
        break;
      case 'adblock':
        this.set('adblockError', true);
        this._closeAdModal();
        this._trackEvent('bits_ads_adblock', requestId, {
          channel: this.get('channelName')
        });
        break;
      case 'limitReached':
        this.set('limitReachedError', true);
        this._closeAdModal();
        this._trackEvent('bits_ads_limit_reached', requestId, {
          channel: this.get('channelName')
        });
        break;
    }
  },

  _trackEvent(eventName, requestId, data) {
    let userName = this.get('session.userData.login');
    let eventData = $.extend({
      device_id: Twitch.idsForMixpanel.getOrCreateUniqueId(),
      login: userName,
      request_id: requestId
    }, data);

    this.get('tracking').trackEvent({
      event: eventName,
      data: eventData
    });
  },

  _trackBitsAdsAvailability(isAvailable) {
    let userName = this.get('session.userData.login');
    let eventData = {
      device_id: Twitch.idsForMixpanel.getOrCreateUniqueId(),
      login: userName,
      channel: this.get('channelName'),
      available: isAvailable
    };

    this.get('tracking').trackEvent({
      event: 'bits_ads_availability',
      data: eventData
    });
  }
});
