"use strict";

var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };

var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };

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

var path = _interopRequire(require("path"));

var fs = _interopRequire(require("fs"));

// Detect previous map
var PreviousMap = (function () {
    function PreviousMap(css, opts) {
        _classCallCheck(this, PreviousMap);

        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;
    }

    // Return SourceMapConsumer object to read map
    PreviousMap.prototype.consumer = function consumer() {
        if (!this.consumerCache) {
            this.consumerCache = new mozilla.SourceMapConsumer(this.text);
        }
        return this.consumerCache;
    };

    // Is map has sources content
    PreviousMap.prototype.withContent = function withContent() {
        return !!(this.consumer().sourcesContent && this.consumer().sourcesContent.length > 0);
    };

    // Is `string` is starting with `start`
    PreviousMap.prototype.startWith = function startWith(string, start) {
        if (!string) return false;
        return string.substr(0, start.length) == start;
    };

    // Load for annotation comment from previous compilation step
    PreviousMap.prototype.loadAnnotation = function loadAnnotation(css) {
        var match = css.match(/\/\*\s*# sourceMappingURL=(.*)\s*\*\//);
        if (match) this.annotation = match[1].trim();
    };

    // Encode different type of inline
    PreviousMap.prototype.decodeInline = function decodeInline(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);
        }
    };

    // Load previous map
    PreviousMap.prototype.loadMap = function loadMap(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;