var shorterNames = require('./shorter-css-color-names');
var REGEX = {
  whitespace: /\s+/g,
  urlHexPairs: /%[\dA-F]{2}/g,
  quotes: /"/g,
}

function collapseWhitespace(str) {
  return str.trim().replace(REGEX.whitespace, ' ');
}

function dataURIPayload(string) {
  return encodeURIComponent(string)
    .replace(REGEX.urlHexPairs, specialHexEncode);
}

// `#` gets converted to `%23`, so quite a few CSS named colors are shorter than
// their equivalent URL-encoded hex codes.
function colorCodeToShorterNames(string) {
  Object.keys(shorterNames).forEach(function(key) {
    if (shorterNames[key].test(string)) {
      string = string.replace(shorterNames[key], key);
    }
  });

  return string;
}

function specialHexEncode(match) {
  switch (match) { // Browsers tolerate these characters, and they're frequent
    case '%20': return ' ';
    case '%3D': return '=';
    case '%3A': return ':';
    case '%2F': return '/';
    default: return match.toLowerCase(); // compresses better
  }
}

function svgToTinyDataUri(svgString) {
  if (typeof svgString !== 'string') {
    throw new TypeError('Expected a string, but received ' + typeof svgString);
  }
  // Strip the Byte-Order Mark if the SVG has one
  if (svgString.charCodeAt(0) === 0xfeff) { svgString = svgString.slice(1) }

  var body = colorCodeToShorterNames(collapseWhitespace(svgString))
    .replace(REGEX.quotes, "'");
  return 'data:image/svg+xml,' + dataURIPayload(body);
}

svgToTinyDataUri.toSrcset = function toSrcset(svgString) {
  return svgToTinyDataUri(svgString).replace(/ /g, '%20');
}

module.exports = svgToTinyDataUri;