import Service from 'ember-service';
import injectService from 'ember-service/inject';
import { API_VERSION } from 'web-client/models/deprecated-stream';
import {
  altRolesExperiment,
  nativeBroadcastsExperiment,
  viewingPartiesExperiment,
  inDateRange
} from 'web-client/utilities/chat-sticky';

const EMPTY_OBJECT = {}; // To prevent unnecessarily creating new objects for every channel change
const EMPTY_ARRAY = []; // To prevent unnecessarily creating new arrays for every channel change
const ACTIVE_CHAT_THRESHOLD = viewingPartiesExperiment.active_chat_threshold || 25;
const VIEWING_PARTY_HOST_LIMIT = viewingPartiesExperiment.host_limit || 3;

export default Service.extend({
  api: injectService(),
  hosts: injectService(),

  altRoleStreams: EMPTY_OBJECT,
  nbStreams: EMPTY_OBJECT,
  viewingPartyHosts: EMPTY_ARRAY,

  updateStickyWithRoom(streamInfo) {
    this._getARStreams(streamInfo);
    this._getNBStreams(streamInfo);
    this._getViewingPartyHosts(streamInfo);
  },

  isValidSticky(experiment, channelName) {
    if (!experiment) {
      return false;
    }

    let isValidChannel = experiment.streams ? experiment.streams[channelName] : true;
    let isValidTime = inDateRange(experiment.start_date, experiment.end_date);

    return isValidTime && isValidChannel;
  },

  _filterLiveStreams(streams) {
    let url = `streams?channel=${Object.keys(streams).join(',')}`;
    return this.get('api').request('get', url, EMPTY_OBJECT, {
      version: API_VERSION
    }).then((response) => {
      if (this.isDestroyed) { return; }
      let liveStreams = {};
      for (let i = 0; i < response.streams.length; i++) {
        let channelName = response.streams[i].channel.name;
        liveStreams[channelName] = streams[channelName];
      }
      return liveStreams;
    });
  },

  _getARStreams(streamInfo) {
    if (!this.isValidSticky(altRolesExperiment, streamInfo.name)) {
      this.set('altRoleStreams', EMPTY_OBJECT);
      return;
    }

    this._filterLiveStreams(altRolesExperiment.streams).then(liveStreams => {
      this.set('altRoleStreams', liveStreams);
    });
  },

  _getNBStreams(streamInfo) {
    if (!this.isValidSticky(nativeBroadcastsExperiment, streamInfo.name)) {
      this.set('nbStreams', EMPTY_OBJECT);
      return;
    }

    this._filterLiveStreams(nativeBroadcastsExperiment.streams).then(liveStreams => {
      this.set('nbStreams', liveStreams);
    });
  },

  _getViewingPartyHosts(streamInfo) {
    if (!this.isValidSticky(viewingPartiesExperiment, streamInfo.name)) {
      this.set('viewingPartyHosts', EMPTY_ARRAY);
      return;
    }
    this.get('hosts').fetchHosts(streamInfo.id, hostCollection => {
      /**
       * Bucket order
       * 0 - Active partner channel user follows
       * 1 - Active channel user follows
       * 2 - Active partner channel
       * 3 - Active channel
       * 4 - Inactive channel user follows
       * 5 - Inactive channel (not displayed)
       */
      let hostBuckets = [ [], [], [], [], [] ];
      for (let i = 0; i < hostCollection.length; i++) {
        let host = hostCollection[i];
        let activity = host.host_recent_chat_activity_count;
        let isActive = activity && activity >= ACTIVE_CHAT_THRESHOLD;
        let bucketIndex = isActive ? 3 : 5;
        if (host.host_followed) {
          bucketIndex = bucketIndex === 3 ? 1 : 4;
        }
        if (host.host_partnered && isActive) {
          bucketIndex--;
        }
        if (bucketIndex < 5) {
          hostBuckets[bucketIndex].push(host);
        }
      }
      let displayedHosts = [];
      let currentBucketIndex = 0;
      while (displayedHosts.length < VIEWING_PARTY_HOST_LIMIT && currentBucketIndex < 5) {
        let currentBucket = hostBuckets[currentBucketIndex];
        for (let i = 0; i < currentBucket.length; i++) {
          displayedHosts.push(currentBucket[i]);
          if (displayedHosts.length === VIEWING_PARTY_HOST_LIMIT) {
            return displayedHosts;
          }
        }
        currentBucketIndex++;
      }

      return displayedHosts;
    }).then(hosts => {
      this.set('viewingPartyHosts', hosts);
      let hostNames = [];
      hosts.forEach(host => {
        hostNames.push(host.url);
      });
      this.set('hostsArray', JSON.stringify(hostNames));
    });
  }

});
