"use strict";

var _classProps = function (child, staticProps, instanceProps) {
  if (staticProps) Object.defineProperties(child, staticProps);
  if (instanceProps) Object.defineProperties(child.prototype, instanceProps);
};

var mozilla = require("source-map");
var Base64 = require("js-base64").Base64;
var path = require("path");
var fs = require("fs");

// Detect previous map
var PreviousMap = (function () {
  var PreviousMap = function PreviousMap(css, opts) {
    this.loadAnnotation(css);
    this.inline = this.startWith(this.annotation, "data:");

    var text = this.loadMap(opts.from, opts.map ? opts.map.prev : undefined);
    if (text) this.text = text;
  };

  _classProps(PreviousMap, null, {
    consumer: {
      writable: true,


      // Return SourceMapConsumer object to read map
      value: function () {
        if (!this.consumerCache) {
          this.consumerCache = new mozilla.SourceMapConsumer(this.text);
        }
        return this.consumerCache;
      }
    },
    withContent: {
      writable: true,


      // Is map has sources content
      value: function () {
        return !!(this.consumer().sourcesContent && this.consumer().sourcesContent.length > 0);
      }
    },
    startWith: {
      writable: true,


      // Is `string` is starting with `start`
      value: function (string, start) {
        if (!string) return false;
        return string.substr(0, start.length) == start;
      }
    },
    loadAnnotation: {
      writable: true,


      // Load for annotation comment from previous compilation step
      value: function (css) {
        var match = css.match(/\/\*\s*# sourceMappingURL=(.*)\s*\*\//);
        if (match) this.annotation = match[1].trim();
      }
    },
    decodeInline: {
      writable: true,


      // Encode different type of inline
      value: function (text) {
        var uri = "data:application/json,";
        var base64 = "data:application/json;base64,";

        if (this.startWith(text, uri)) {
          return decodeURIComponent(text.substr(uri.length));
        } else if (this.startWith(text, base64)) {
          return Base64.decode(text.substr(base64.length));
        } else {
          var encoding = text.match(/data:application\/json;([^,]+),/)[1];
          throw new Error("Unsupported source map encoding " + encoding);
        }
      }
    },
    loadMap: {
      writable: true,


      // Load previous map
      value: function (file, prev) {
        if (prev === false) return;

        if (prev) {
          if (typeof (prev) == "string") {
            return prev;
          } else if (prev instanceof mozilla.SourceMapConsumer) {
            return mozilla.SourceMapGenerator.fromSourceMap(prev).toString();
          } else if (prev instanceof mozilla.SourceMapGenerator) {
            return prev.toString();
          } else if (typeof (prev) == "object" && prev.mappings) {
            return JSON.stringify(prev);
          } else {
            throw new Error("Unsupported previous source map format: " + prev.toString());
          }
        } else if (this.inline) {
          return this.decodeInline(this.annotation);
        } else if (this.annotation) {
          var map = this.annotation;
          if (file) map = path.join(path.dirname(file), map);

          this.root = path.dirname(map);
          if (fs.existsSync && fs.existsSync(map)) {
            return fs.readFileSync(map, "utf-8").toString().trim();
          }
        }
      }
    }
  });

  return PreviousMap;
})();

module.exports = PreviousMap;