'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var through = _interopDefault(require('through'));
var tokenize = _interopDefault(require('html-tokenize'));
var pipe = _interopDefault(require('multipipe'));

var createExtractCritical = function createExtractCritical(emotion) {
  return function (html) {
    // parse out ids from html
    // reconstruct css/rules/cache to pass
    var RGX = new RegExp(emotion.caches.key + "-([a-zA-Z0-9-_]+)", 'gm');
    var o = {
      html: html,
      ids: [],
      css: ''
    };
    var match;
    var ids = {};

    while ((match = RGX.exec(html)) !== null) {
      // $FlowFixMe
      if (ids[match[1]] === undefined) {
        // $FlowFixMe
        ids[match[1]] = true;
      }
    }

    o.ids = Object.keys(emotion.caches.inserted).filter(function (id) {
      if ((ids[id] === true || emotion.caches.registered[emotion.caches.key + "-" + id] === undefined) && emotion.caches.inserted[id] !== true) {
        o.css += emotion.caches.inserted[id];
        return true;
      }
    });
    return o;
  };
};

function generateStyleTag(cssKey, ids, styles, nonceString) {
  return "<style data-emotion-" + cssKey + "=\"" + ids.substring(1) + "\"" + nonceString + ">" + styles + "</style>";
}

var createRenderStylesToString = function createRenderStylesToString(emotion, nonceString) {
  return function (html) {
    var _emotion$caches = emotion.caches,
        inserted = _emotion$caches.inserted,
        cssKey = _emotion$caches.key,
        registered = _emotion$caches.registered;
    var regex = new RegExp("<|" + cssKey + "-([a-zA-Z0-9-_]+)", 'gm');
    var seen = {};
    var result = '';
    var globalIds = '';
    var globalStyles = '';

    for (var id in inserted) {
      if (inserted.hasOwnProperty(id)) {
        var style = inserted[id];
        var key = cssKey + "-" + id;

        if (style !== true && registered[key] === undefined) {
          globalStyles += style;
          globalIds += " " + id;
        }
      }
    }

    if (globalStyles !== '') {
      result = generateStyleTag(cssKey, globalIds, globalStyles, nonceString);
    }

    var ids = '';
    var styles = '';
    var lastInsertionPoint = 0;
    var match;

    while ((match = regex.exec(html)) !== null) {
      // $FlowFixMe
      if (match[0] === '<') {
        if (ids !== '') {
          result += generateStyleTag(cssKey, ids, styles, nonceString);
          ids = '';
          styles = '';
        } // $FlowFixMe


        result += html.substring(lastInsertionPoint, match.index); // $FlowFixMe

        lastInsertionPoint = match.index;
        continue;
      } // $FlowFixMe


      var _id = match[1];
      var _style = inserted[_id];

      if (_style === true || seen[_id]) {
        continue;
      }

      seen[_id] = true;
      styles += _style;
      ids += " " + _id;
    }

    result += html.substring(lastInsertionPoint);
    return result;
  };
};

var createRenderStylesToNodeStream = function createRenderStylesToNodeStream(emotion, nonceString) {
  return function () {
    var insed = {};
    var tokenStream = tokenize();
    var inlineStream = through(function write(thing) {
      var type = thing[0],
          data = thing[1];

      if (type === 'open') {
        var css = '';
        var ids = {};
        var match;
        var fragment = data.toString();
        var regex = new RegExp(emotion.caches.key + "-([a-zA-Z0-9-_]+)", 'gm');

        while ((match = regex.exec(fragment)) !== null) {
          if (match !== null && insed[match[1]] === undefined) {
            ids[match[1]] = true;
          }
        }

        Object.keys(emotion.caches.inserted).forEach(function (id) {
          if (emotion.caches.inserted[id] !== true && insed[id] === undefined && (ids[id] === true || emotion.caches.registered[emotion.caches.key + "-" + id] === undefined && (ids[id] = true))) {
            insed[id] = true; // $FlowFixMe flow thinks emotion.caches.inserted[id] can be true even though it's checked earlier

            css += emotion.caches.inserted[id];
          }
        });

        if (css !== '') {
          this.queue("<style data-emotion-" + emotion.caches.key + "=\"" + Object.keys(ids).join(' ') + "\"" + nonceString + ">" + css + "</style>");
        }
      }

      this.queue(data);
    }, function end() {
      this.queue(null);
    });
    return pipe(tokenStream, inlineStream);
  };
};

function index (emotion) {
  var nonceString = emotion.caches.nonce !== undefined ? " nonce=\"" + emotion.caches.nonce + "\"" : '';
  return {
    extractCritical: createExtractCritical(emotion),
    renderStylesToString: createRenderStylesToString(emotion, nonceString),
    renderStylesToNodeStream: createRenderStylesToNodeStream(emotion, nonceString)
  };
}

module.exports = index;
