import Service from 'ember-service';
import injectService from 'ember-service/inject';
import computed from 'ember-computed';
import {
  CHEER_PREFIX,
  CHEERMOTE_BG_LIGHT,
  CHEERMOTE_BG_DARK
} from 'web-client/utilities/bits/constants-config';

const DEFAULT_ASSET_SIZE = 1;

export default Service.extend({
  bits: injectService(),
  layout: injectService(),
  chatSettings: injectService(),

  prefixes: null,
  regexes: null,
  emoteConfig: null,
  emoteImageMap: null,
  isLoaded: false,
  cachedConfigPromise: null,

  isDarkChat: computed.or('layout.isTheatreMode', 'chatSettings.darkMode'),

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

    let cachedConfigPromise = this.get('cachedConfigPromise');
    if (!cachedConfigPromise) {
      cachedConfigPromise = this.get('bits').getActions().then((actions) => {
        if (this.isDestroyed) {
          return;
        }

        let {
          prefixes,
          regexes,
          emoteConfig,
          emoteImageMap
        } = this._parseActionsPayload(actions);

        this.set('prefixes', prefixes);
        this.set('regexes', regexes);
        this.set('emoteImageMap', emoteImageMap);
        this.set('isLoaded', true);

        // for some reason, this needs to be set last for FFZ to work /shrug
        this.set('emoteConfig', emoteConfig);
      });
      this.set('cachedConfigPromise', cachedConfigPromise);
    }
  },

  getImageSrc(amount, prefix, useDarkAssets, useStaticAssets, size) {
    if (!this.get('isLoaded')) {
      return;
    }
    prefix = prefix ? prefix.toLowerCase() : '';
    if (!this._isPrefixValid(prefix)) {
      return;
    }

    let assetTierId = this._getAssetTierId(amount, prefix);
    let assetBg = this._getAssetBg(useDarkAssets);
    let assetStyle = this._getAssetStyle(useStaticAssets);

    return this.get('emoteImageMap')[prefix][assetTierId][assetBg][assetStyle][size];
  },

  getImageSrcSet(amount, prefix, useDarkAssets, useStaticAssets, size) {
    if (!this.get('isLoaded')) {
      return;
    }
    prefix = prefix ? prefix.toLowerCase() : '';
    if (!this._isPrefixValid(prefix)) {
      return;
    }

    // Not generating srcSet for sizes > 1
    if (size !== DEFAULT_ASSET_SIZE) {
      return;
    }

    let assetTierInfo = this._getAssetTierInfo(amount, prefix);
    let assetBg = this._getAssetBg(useDarkAssets);
    let assetStyle = this._getAssetStyle(useStaticAssets);
    let assetSizes = this.get('emoteConfig')[prefix].scales;

    return assetSizes.map((thisSize) => {
      let srcSetUrl = assetTierInfo.images[assetBg][assetStyle][thisSize];
      return `${srcSetUrl} ${thisSize}x`;
    }).join(', ');
  },

  getTierColor(amount, prefix) {
    if (!this.get('isLoaded')) {
      return;
    }
    prefix = prefix ? prefix.toLowerCase() : '';
    if (!this._isPrefixValid(prefix)) {
      return;
    }

    let tiers = this.get('emoteConfig')[prefix].tiers;
    let tierId = this._getAssetTierId(amount, prefix);

    let tier = tiers.filterBy('id', `${tierId}`)[0];
    return tier.color;
  },

  getTiers(prefix) {
    if (!this.get('isLoaded')) {
      return [];
    }
    prefix = prefix ? prefix.toLowerCase() : '';
    if (!this._isPrefixValid(prefix)) {
      return [];
    }

    return this.get('emoteConfig')[prefix].tiers.map((tier) => {
      return tier.min_bits;
    });
  },

  getPrefixData(prefix) {
    if (!this.get('isLoaded')) {
      return;
    }
    prefix = prefix ? prefix.toLowerCase() : '';
    if (!this._isPrefixValid(prefix)) {
      return;
    }

    return this.get('emoteConfig')[prefix];
  },

  getMessagePrefix(message) {
    message = message.trim();

    if (!this.get('isLoaded') || message === '') {
      return CHEER_PREFIX;
    }

    let regexes = this.get('regexes');
    let words = message.split(/\s+/);
    let prefixCount = 0;
    let lastSeenPrefix = CHEER_PREFIX;

    regexes.forEach((regex) => {
      if (words.some((word) => word.match(regex.valid))) {
        lastSeenPrefix = regex.prefix;
        prefixCount += 1;
      }
    });

    return prefixCount === 1 ? lastSeenPrefix : CHEER_PREFIX;
  },

  _isPrefixValid(prefix) {
    if (!prefix) {
      return false;
    }

    let emoteConfig = this.get('emoteConfig');
    let emoteImageMap = this.get('emoteImageMap');

    if (!emoteImageMap.hasOwnProperty(prefix)) {
      return false;
    }

    let hasTiers = emoteConfig[prefix].tiers && emoteConfig[prefix].tiers.length > 0;
    let hasSizes = emoteConfig[prefix].scales && emoteConfig[prefix].scales.length > 0;
    return hasTiers && hasSizes;
  },

  _getAssetTierInfo(amount, prefix) {
    let tiers = this.get('emoteConfig')[prefix].tiers;
    if (amount <= 0) {
      return tiers[0];
    }

    let bitsTier;
    for (let i = 0; i < tiers.length; i++) {
      let nextTier = tiers[i];

      if (amount >= nextTier.min_bits) {
        bitsTier = nextTier;
      } else {
        break;
      }
    }

    return bitsTier;
  },

  _getAssetTierId(amount, prefix) {
    let tiers = this.get('emoteConfig')[prefix].tiers;

    // default to lowest tier
    let tierId = 1;
    if (amount <= 0) {
      return tierId;
    }

    // if there's a higher tier the amount reaches, use that
    tiers.forEach((tier) => {
      if (amount >= tier.min_bits) {
        tierId = tier.min_bits;
      }
    });
    return tierId;
  },

  _getAssetBg(useDarkAssets) {
    return useDarkAssets ? CHEERMOTE_BG_DARK : CHEERMOTE_BG_LIGHT;
  },

  _getAssetStyle(useStaticAssets) {
    return useStaticAssets ? 'static' : 'animated';
  },

  _parseActionsPayload(payload) {
    let prefixes = [];
    let regexes = [];
    let emoteConfig = {};
    let emoteImageMap = {};

    let prefix;
    payload.actions.forEach((action) => {
      prefix = action.prefix;
      prefixes.push(prefix);
      regexes.push({
        prefix: prefix,
        zeroValue: new RegExp(`^\\s*${prefix}0+\\s*$`, 'i'),
        valid: new RegExp(`^\\s*${prefix}\\d+\\s*$`, 'i')
      });

      emoteConfig[prefix.toLowerCase()] = action;
    });

    prefixes.forEach((thisPrefix) => {
      let prefixLowerCase = thisPrefix.toLowerCase();
      let action = emoteConfig[prefixLowerCase];
      emoteImageMap[prefixLowerCase] = {};

      action.tiers.forEach((tier) => {
        let tierId = tier.id;
        emoteImageMap[prefixLowerCase][tierId] = {};

        action.backgrounds.forEach((background) => {
          emoteImageMap[prefixLowerCase][tierId][background] = {};

          action.states.forEach((state) => {
            emoteImageMap[prefixLowerCase][tierId][background][state] = {};

            action.scales.forEach((scale) => {
              emoteImageMap[prefixLowerCase][tierId][background][state][scale] = tier.images[background][state][scale];
            });
          });
        });
      });
    });

    return {
      prefixes,
      regexes,
      emoteConfig,
      emoteImageMap
    };
  }
});
