import injectService from 'ember-service/inject';
import Service from 'ember-service';
import urlParams from 'web-client/utilities/url-params';
import { viewingPartiesExperiment } from 'web-client/utilities/chat-sticky';
import RSVP from 'rsvp';

let tmiHostport = 'tmi.twitch.tv',
    forceHost = urlParams.tmi_host,
    forcePort = parseInt(urlParams.tmi_port);

if (forceHost) {
  let HOST_WHITELIST = [ /\.twitch\.tv/ ];
  let rejected = true;

  for (let index in HOST_WHITELIST) {
    if (HOST_WHITELIST[index].test(forceHost)) {
      rejected = false;
      tmiHostport = forcePort ? `${forceHost}:${forcePort}` : forceHost;

      break;
    }
  }

  if (rejected) {
    let error = "Non-whitelisted tmi_host";
    console.error(error);
    throw error;
  }
}

const corsOptions = {
  method: 'GET',
  dataType: 'json',
  contentType: 'application/json',
  cache: true,
  global: false,
  retryNum: 0
};

export default Service.extend({
  ajax: injectService(),
  api: injectService(),
  session: injectService(),
  store: injectService(),

  _requestHostsByTarget(channelId) {
    let hostPromiseName = `_${channelId}HostPromise`;

    if (this.get(hostPromiseName)) {
      return this.get(hostPromiseName);
    }
    let hostsSrc = `https://${tmiHostport}/hosts?target=${channelId}&include_logins=1`;

    let { userData } = this.get('session');
    if (userData) {
      corsOptions.headers = {
        Authorization: `OAuth ${userData.chat_oauth_token}`
      };
    }

    let hostsPromise = this.get('ajax').request(hostsSrc, corsOptions)
      .then(res => res.hosts)
      .catch(e => {
        if (e.status && e.status >= 400) {
          this.set(hostPromiseName, null);
          return; /* Swallow this error */
        }
        throw e; /* Rethrow unexpected error */
      });

    this.set(hostPromiseName, hostsPromise);

    return hostsPromise;
  },

  // filter is optional callback that can replace the _truncateHostList invocation
  fetchHosts(channelId, filter) {
    if (channelId === null || channelId === undefined) {
      return RSVP.Promise.resolve([]);
    }
    return this._requestHostsByTarget(channelId).then(hostCollection => {
      if (filter) {
        hostCollection = filter(hostCollection);
      } else {
        hostCollection = this._truncateHostList(hostCollection, viewingPartiesExperiment.host_limit);
      }
      return hostCollection.map((hostingObj, index) => {
        return {
          name: hostingObj.host_display_name || hostingObj.host_login,
          url: `${hostingObj.host_login}`,
          order: index
        };
      });
    }).catch(err => {
      console.error(err);
    });
  },

  _truncateHostList(hostList=[], limit=3) {
    // If list already under limit, no need to mutate
    if (limit > hostList.length) {
      return hostList;
    }
    hostList = this._randomizeHostOrder(hostList);
    let truncatedList = [];
    for (let i = 0; i < limit; i++) {
      truncatedList.push(hostList.pop());
    }
    return truncatedList;
  },

  _randomizeHostOrder(hostList=[]) {
    for (let i = 0; i < hostList.length; i++) {
      let randIndex = Math.floor(Math.random() * hostList.length);
      let temp = hostList[i];
      hostList[i] = hostList[randIndex];
      hostList[randIndex] = temp;
    }
    return hostList;
  }

});
