"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/// <reference path="../../../typings/main.d.ts" />
var lowlevel = require("../lowLevelAST");
var path = require("path");
var url = require("url");
var fs = require("fs");
var yaml = require("yaml-ast-parser");
var _ = require("underscore");
var textutil = require("../../util/textutil");
var hli = require("../highLevelImpl");
var services = require("../definition-system/ramlServices");
var rr = require("./resourceRegistry");
var util = require("../../util/index");
var refResolvers = require("./includeRefResolvers");
var schemes = require("../../util/schemaAsync");
var universes = require("../tools/universe");
var expander = require("../ast.core/expanderLL");
var namespaceResolver = require("../ast.core/namespaceResolver");
var linter = require("../ast.core/linter");
var messageRegistry = require("../../../resources/errorMessages");
var Error = yaml.YAMLException;
exports.Kind = {
    SCALAR: yaml.Kind.SCALAR
};
var MarkupIndentingBuffer = /** @class */ (function () {
    function MarkupIndentingBuffer(indent) {
        this.text = '';
        this.indent = indent;
    }
    MarkupIndentingBuffer.prototype.isLastNL = function () {
        return this.text.length > 0 && this.text[this.text.length - 1] == '\n';
    };
    MarkupIndentingBuffer.prototype.addWithIndent = function (lev, s) {
        if (this.isLastNL()) {
            this.text += textutil.indent(lev);
            this.text += this.indent;
        }
        this.text += s;
    };
    MarkupIndentingBuffer.prototype.addChar = function (ch) {
        if (this.isLastNL()) {
            this.text += this.indent;
        }
        this.text += ch;
    };
    MarkupIndentingBuffer.prototype.append = function (s) {
        for (var i = 0; i < s.length; i++) {
            this.addChar(s[i]);
        }
    };
    return MarkupIndentingBuffer;
}());
exports.MarkupIndentingBuffer = MarkupIndentingBuffer;
var CompilationUnit = /** @class */ (function () {
    function CompilationUnit(_path, _content, _tl, _project, _apath) {
        this._path = _path;
        this._content = _content;
        this._tl = _tl;
        this._project = _project;
        this._apath = _apath;
        this._includedByPaths = [];
        this._path = this._path != null ? this._path.replace(/\\/g, "/") : null;
    }
    CompilationUnit.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), CompilationUnit.CLASS_IDENTIFIER);
    };
    CompilationUnit.prototype.getClassIdentifier = function () {
        var superIdentifiers = [];
        return superIdentifiers.concat(CompilationUnit.CLASS_IDENTIFIER);
    };
    CompilationUnit.prototype.highLevel = function () {
        if (this._hl) {
            return this._hl;
        }
        this._hl = hli.fromUnit(this);
        return this._hl;
    };
    CompilationUnit.prototype.isStubUnit = function () {
        return this.stu;
    };
    CompilationUnit.prototype.resolveAsync = function (p) {
        var unit = this._project.resolveAsync(this._path, p);
        return unit;
    };
    CompilationUnit.prototype.getIncludeNodes = function () {
        var ast = this.ast();
        var arr = [];
        if (ast == null)
            return [];
        ast.gatherIncludes(arr);
        ast.children().forEach(function (x) {
            if (x.key() == "uses") {
                x.children().forEach(function (y) {
                    arr.push({
                        includePath: function () {
                            var val = y.value();
                            if (typeof (val) != "string")
                                return null;
                            return val;
                        }
                    });
                });
            }
        });
        return arr;
    };
    CompilationUnit.prototype.cloneToProject = function (p) {
        var newUnit = new CompilationUnit(this._path, this._content, this._tl, p, this._apath);
        return newUnit;
    };
    CompilationUnit.prototype.clone = function () {
        var newUnit = new CompilationUnit(this._path, this._content, this._tl, this.project(), this._apath);
        return newUnit;
    };
    CompilationUnit.prototype.stub = function () {
        var newUnit = new CompilationUnit(this._path, this._content, this._tl, this.project(), this._apath);
        newUnit.stu = true;
        return newUnit;
    };
    CompilationUnit.prototype.isDirty = function () {
        return false;
    };
    CompilationUnit.prototype.expandedHighLevel = function () {
        if (this.expanded) {
            return this.expanded;
        }
        var result = this.highLevel().asElement();
        var nm = expander.expandTraitsAndResourceTypes(result.wrapperNode());
        var hlnode = nm.highLevel();
        hlnode._expanded = true;
        this.expanded = hlnode;
        return hlnode;
    };
    CompilationUnit.prototype.absolutePath = function () {
        return this._apath;
    };
    CompilationUnit.prototype.isRAMLUnit = function () {
        var p = this.absolutePath();
        if (lowlevel.isWebPath(p)) {
            try {
                p = url.parse(p).pathname;
            }
            catch (e) {
                p = this._path;
            }
        }
        var en = path.extname(p);
        if (en == '.raml' || en == '.yaml' || en == '.yml') {
            return true;
        }
        else if (!en) {
            if (!this._content) {
                return false;
            }
            var contentTrim = this._content.trim();
            if (util.stringStartsWith(contentTrim, "#%RAML")) {
                return true;
            }
            var arr = contentTrim.split("\n");
            var line1 = void 0;
            for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
                var str = arr_1[_i];
                var lTrim = str.trim();
                if (!lTrim || util.stringStartsWith(lTrim, "#")) {
                    continue;
                }
                line1 = str;
                break;
            }
            if (!line1) {
                return true;
            }
            try {
                var result = yaml.load(line1, { ignoreDuplicateKeys: true });
                return result.kind != yaml.Kind.SCALAR;
            }
            catch (e) {
                return false;
            }
        }
        return false;
    };
    CompilationUnit.prototype.contents = function () {
        return this._content;
    };
    CompilationUnit.prototype.resolve = function (p) {
        if (typeof p != "string") {
            return null;
        }
        var unit = this._project.resolve(this._path, p);
        return unit;
    };
    CompilationUnit.prototype.path = function () {
        return this._path;
    };
    CompilationUnit.prototype.lexerErrors = function () {
        if (this.errors == null) {
            this.ast();
        }
        return this.errors;
    };
    CompilationUnit.prototype.ast = function () {
        var _this = this;
        if (this._node) {
            return this._node;
        }
        try {
            var result = yaml.load(this._content, { ignoreDuplicateKeys: true });
            this.errors = result.errors;
            this.errors.forEach(function (x) {
                if (x.mark) {
                    x.mark.filePath = _this.absolutePath();
                }
            });
            this._node = new ASTNode(result, this, null, null, null);
            this._node._errors = this.errors;
            return this._node;
        }
        catch (e) {
            this.errors = [];
            this.errors.push(new Error(e.message));
            //console.log(this._content)
            //console.log(e)
            this._node = null;
            return this._node;
        }
    };
    CompilationUnit.prototype.isTopLevel = function () {
        return this._tl;
    };
    CompilationUnit.prototype.updateContent = function (n) {
        this._content = n;
        this.errors = null;
        this._node = null; //todo incremental update
        this._lineMapper = null;
    };
    CompilationUnit.prototype.updateContentSafe = function (n) {
        this._content = n;
        this._lineMapper = null;
        this._hl = null;
    };
    CompilationUnit.prototype.project = function () {
        return this._project;
    };
    CompilationUnit.prototype.lineMapper = function () {
        if (this._lineMapper == null) {
            this._lineMapper = new lowlevel.LineMapperImpl(this.contents(), this.absolutePath());
        }
        return this._lineMapper;
    };
    //ramlVersion():string{
    //    return this._ramlVersion;
    //}
    /**
     * Returns true if this unit is overlay or extension, false otherwise.
     */
    CompilationUnit.prototype.isOverlayOrExtension = function () {
        var contents = this.contents();
        var spec = "";
        var ptype = null;
        var num = 0;
        var pt = 0;
        for (var n = 0; n < contents.length; n++) {
            var c = contents.charAt(n);
            if (c == '\r' || c == '\n') {
                if (spec) {
                    ptype = contents.substring(pt, n).trim();
                }
                else {
                    spec = contents.substring(0, n).trim();
                }
                break;
            }
            if (c == ' ') {
                num++;
                if (!spec && num == 2) {
                    spec = contents.substring(0, n);
                    pt = n;
                }
            }
        }
        return ptype == "Extension" || ptype == "Overlay";
    };
    /**
     * Returns master reference if presents, null otherwise.
     */
    CompilationUnit.prototype.getMasterReferenceNode = function () {
        return _.find(this.ast().children(), function (x) { return x.key() == universes.Universe10.Overlay.properties.extends.name; });
    };
    CompilationUnit.prototype.addIncludedBy = function (path) {
        if (!this.includedByContains(path)) {
            this._includedByPaths.push(path);
        }
    };
    CompilationUnit.prototype.includedByContains = function (path) {
        return _.find(this._includedByPaths, function (currentPath) { return currentPath == path; }) != null;
    };
    CompilationUnit.prototype.getIncludedByPaths = function () {
        return this._includedByPaths;
    };
    CompilationUnit.CLASS_IDENTIFIER = "jsyaml2lowLevel.CompilationUnit";
    return CompilationUnit;
}());
exports.CompilationUnit = CompilationUnit;
var XhrSync = require('xmlhttprequest').XMLHttpRequest;
var XhrAsync = require('xhr2').XMLHttpRequest;
var XMLHttpRequestWrapper = /** @class */ (function () {
    function XMLHttpRequestWrapper() {
    }
    XMLHttpRequestWrapper.prototype.open = function (method, url, async) {
        this.xhr = async ? new XhrAsync() : new XhrSync();
        this.async = async;
        this.xhr.open(method, url, async);
    };
    XMLHttpRequestWrapper.prototype.setRequestHeader = function (name, value) {
        this.xhr.setRequestHeader(name, value);
    };
    XMLHttpRequestWrapper.prototype.getResponseHeader = function (name) {
        return this.xhr.getResponseHeader(name);
    };
    XMLHttpRequestWrapper.prototype.getAllResponseHeaders = function () {
        return this.xhr.getAllResponseHeaders();
    };
    XMLHttpRequestWrapper.prototype.send = function (content) {
        var _this = this;
        this.xhr.onload = function () { return _this.onResponse(false); };
        this.xhr.onerror = function () { return _this.onResponse(true); };
        this.xhr.send(content);
    };
    XMLHttpRequestWrapper.prototype.onResponse = function (isError) {
        this.statusText = this.xhr.statusText;
        this.responseText = this.xhr.responseText;
        this.responseType = this.xhr.responseType;
        this.status = this.xhr.status;
        if (isError && this.onerror) {
            this.onerror();
            return;
        }
        if (this.onload) {
            this.onload();
        }
    };
    return XMLHttpRequestWrapper;
}());
exports.XMLHttpRequestWrapper = XMLHttpRequestWrapper;
function buildXHR() {
    return new XMLHttpRequestWrapper();
}
exports.buildXHR = buildXHR;
var SimpleExecutor = /** @class */ (function () {
    function SimpleExecutor() {
    }
    SimpleExecutor.prototype.execute = function (req, doAppendParams) {
        if (doAppendParams === void 0) { doAppendParams = true; }
        var xhr = buildXHR();
        var url = req.url;
        if (doAppendParams) {
            url = this.appendParams(req, req.url);
        }
        xhr.open(req.method, url, false);
        this.doRequest(req, xhr);
        //rheaders=xhr.getAllResponseHeaders();
        var status = xhr.status;
        if (status > 300 && status < 400) {
            var locHeader = xhr.getResponseHeader('location');
            if (locHeader) {
                req.url = locHeader;
                return this.execute(req, false);
            }
        }
        var response = {
            status: status,
            statusText: xhr.statusText,
            headers: xhr.getAllResponseHeaders().split('\n').map(function (x) {
                var ind = x.indexOf(':');
                return {
                    name: x.substring(0, ind).trim(),
                    value: x.substring(ind + 1).trim()
                };
            }),
            content: {
                text: xhr.responseText,
                mimeType: xhr.responseType
            }
        };
        return response;
    };
    SimpleExecutor.prototype.appendParams = function (req, url) {
        var gotQueryParams = (req.queryString && req.queryString.length > 0);
        if (gotQueryParams) {
            url = url + '?';
            var arr = [];
            if (gotQueryParams) {
                arr = arr.concat(req.queryString.map(function (q) {
                    return encodeURIComponent(q.name) + '=' + encodeURIComponent(q.value);
                }));
            }
            url += arr.join('&');
        }
        return url;
    };
    SimpleExecutor.prototype.log = function (varName, value) {
    };
    SimpleExecutor.prototype.executeAsync = function (req, doAppendParams) {
        if (doAppendParams === void 0) { doAppendParams = true; }
        var xhr = buildXHR();
        var url = req.url;
        if (doAppendParams) {
            url = this.appendParams(req, req.url);
        }
        var outer = this;
        return new Promise(function (resolve, reject) {
            xhr.open(req.method, url, true);
            xhr.onload = function () {
                var status = xhr.status;
                var response = {
                    status: status,
                    statusText: xhr.statusText,
                    headers: xhr.getAllResponseHeaders().split('\n').map(function (x) {
                        var ind = x.indexOf(':');
                        return {
                            name: x.substring(0, ind).trim(),
                            value: x.substring(ind + 1).trim()
                        };
                    }),
                    content: {
                        text: xhr.responseText,
                        mimeType: xhr.responseType
                    }
                };
                resolve(response);
            };
            xhr.onerror = function () {
                reject(new Error(messageRegistry.NETWORK_ERROR.message));
            };
            outer.doRequest(req, xhr);
        });
    };
    SimpleExecutor.prototype.doRequest = function (req, xhr) {
        if (req.headers) {
            req.headers.forEach(function (x) { return xhr.setRequestHeader(x.name, x.value); });
        }
        if (req.postData) {
            if (req.postData.params) {
                var body = req.postData.params.map(function (p) { return encodeURIComponent(p.name) + '=' + encodeURIComponent(p.value); }).join('&');
                xhr.send(body);
            }
            else {
                xhr.send(req.postData.text);
            }
        }
        else {
            xhr.send();
        }
    };
    return SimpleExecutor;
}());
exports.SimpleExecutor = SimpleExecutor;
var HTTPResolverImpl = /** @class */ (function () {
    function HTTPResolverImpl() {
        this.executor = new SimpleExecutor();
    }
    HTTPResolverImpl.prototype.getResource = function (url) {
        if (typeof atom !== 'undefined' && atom != null) {
            var cached = rr.get(url);
            if (cached) {
                return cached;
            }
            rr.addNotify(url);
            try {
                var resultWithCallback = {
                    content: ""
                };
                this.getResourceAsync(url).then(function (x) {
                    try {
                        if (x.errorMessage) {
                            rr.set(url, { content: null, errorMessage: null });
                        }
                        else {
                            x.errorMessage = null;
                            rr.set(url, x);
                        }
                    }
                    finally {
                        if (resultWithCallback.callback) {
                            resultWithCallback.callback(rr.get(url));
                        }
                        rr.removeNotity(url);
                    }
                }, function (e) {
                    rr.set(url, { content: null, errorMessage: null });
                    if (resultWithCallback.callback) {
                        resultWithCallback.callback(rr.get(url));
                    }
                    rr.removeNotity(url);
                });
                return resultWithCallback;
            }
            catch (e) {
                console.log("Error");
                console.log(e);
            }
        }
        var response = this.executor.execute({
            method: 'get',
            url: url
        });
        if (!response) {
            throw new Error(linter.applyTemplate(messageRegistry.UNABLE_TO_EXECUTE_GET, { url: url }));
        }
        var result = this.toResponse(response, url);
        return result;
    };
    HTTPResolverImpl.prototype.getResourceAsync = function (url) {
        var _this = this;
        return this.executor.executeAsync({
            method: 'get',
            url: url
        }).then(function (x) {
            if (!x) {
                return Promise.reject(new Error(linter.applyTemplate(messageRegistry.UNABLE_TO_EXECUTE_GET, { url: url })));
            }
            var result = _this.toResponse(x, url);
            return result;
        }, function (x) {
            return Promise.reject(linter.applyTemplate(messageRegistry.UNABLE_TO_EXECUTE_GET, { url: url }));
        });
    };
    HTTPResolverImpl.prototype.toResponse = function (response, url) {
        var msg = null;
        if (response.status >= 400) {
            msg = "GET " + url + "\nreturned error: " + response.status;
            if (response.statusText) {
                msg += " " + response.statusText;
            }
        }
        var content = null;
        if (response.content && response.content.text) {
            content = response.content.text;
        }
        var result = {
            content: content,
            errorMessage: msg
        };
        return result;
    };
    return HTTPResolverImpl;
}());
exports.HTTPResolverImpl = HTTPResolverImpl;
var FSResolverImpl = /** @class */ (function () {
    function FSResolverImpl() {
    }
    FSResolverImpl.prototype.content = function (path) {
        if (typeof path != "string") {
            path = "" + path;
        }
        if (!fs.existsSync(path)) {
            return null;
        }
        try {
            return fs.readFileSync(path).toString();
        }
        catch (e) {
            return null;
        }
    };
    FSResolverImpl.prototype.list = function (path) {
        return fs.readdirSync(path);
    };
    FSResolverImpl.prototype.contentAsync = function (path) {
        return new Promise(function (resolve, reject) {
            fs.readFile(path, function (err, data) {
                if (err != null) {
                    return reject(err);
                }
                var content = data.toString();
                resolve(content);
            });
        });
    };
    FSResolverImpl.prototype.listAsync = function (path) {
        return new Promise(function (reject, resolve) {
            fs.readdir(path, function (err, files) {
                if (err != null) {
                    return Promise.reject(err);
                }
                resolve(files);
            });
        });
    };
    return FSResolverImpl;
}());
exports.FSResolverImpl = FSResolverImpl;
function copyNode(n) {
    if (n == null) {
        return null;
    }
    switch (n.kind) {
        case yaml.Kind.SCALAR:
            return {
                errors: [],
                startPosition: n.startPosition,
                endPosition: n.endPosition,
                value: n.value,
                kind: yaml.Kind.SCALAR,
                parent: n.parent
            };
        case yaml.Kind.MAPPING:
            var map = n;
            return {
                errors: [],
                key: copyNode(map.key),
                value: copyNode(map.value),
                startPosition: map.startPosition,
                endPosition: map.endPosition,
                kind: yaml.Kind.MAPPING,
                parent: map.parent
            };
        case yaml.Kind.MAP:
            var ymap = n;
            return {
                errors: [],
                startPosition: n.startPosition,
                endPosition: n.endPosition,
                mappings: ymap.mappings.map(function (x) { return copyNode(x); }),
                kind: yaml.Kind.MAP,
                parent: ymap.parent
            };
    }
    return n;
}
var innerShift = function (offset, yaNode, shift) {
    if (!yaNode)
        return;
    if (yaNode.startPosition >= offset) {
        yaNode.startPosition += shift;
    }
    if (yaNode.endPosition > offset) {
        yaNode.endPosition += shift;
    }
    //this kind is a separate case
    if (yaNode.kind == yaml.Kind.MAPPING) {
        var m = yaNode;
        innerShift(offset, m.key, shift);
        innerShift(offset, m.value, shift);
    }
};
function splitOnLines(text) {
    var lines = text.match(/^.*((\r\n|\n|\r)|$)/gm);
    return lines;
}
//TODO IMPROVE INDENTS
function stripIndent(text, indent) {
    var lines = splitOnLines(text);
    var rs = [];
    for (var i = 0; i < lines.length; i++) {
        if (i == 0) {
            rs.push(lines[0]);
        }
        else {
            rs.push(lines[i].substring(indent.length));
        }
    }
    return rs.join("");
}
var leadingIndent = function (node, text) {
    var leading = "";
    var pos = node.start() - 1;
    //if(pos > 0 && text[pos] == ' ' && text[pos-1] == '-') {
    //    // seq here
    //    pos -= 2;
    //}
    while (pos > 0) {
        var ch = text[pos];
        //if (ch == '\r' || ch == '\n' || ch != ' ') break;
        //console.log('char: [' + ch + ']');
        if (ch != ' ' && ch != '-')
            break;
        leading = ' ' + leading;
        pos--;
    }
    return leading;
};
function indent(line) {
    var rs = "";
    for (var i = 0; i < line.length; i++) {
        var c = line[i];
        if (c == '\r' || c == '\n') {
            continue;
        }
        if (c == ' ' || c == '\t') {
            rs += c;
            continue;
        }
        break;
    }
    return rs;
}
function indentLines(s, indent) {
    return s.split("\n").map(function (x) {
        if (x.trim().length == 0) {
            return x;
        }
        return indent + x;
    }).join("\n");
}
function extraIndent(text, indent) {
    var lines = splitOnLines(text);
    var rs = [];
    for (var i = 0; i < lines.length; i++) {
        if (i == 0) {
            rs.push(lines[0]);
        }
        else {
            if (lines[i].trim().length > 0) {
                rs.push(indent + lines[i]);
            }
            else {
                rs.push("");
            }
        }
    }
    return rs.join("");
}
var Project = /** @class */ (function () {
    /**
     *
     * @param rootPath - path to folder where your root api is located
     * @param resolver
     * @param _httpResolver
     */
    function Project(rootPath, resolver, _httpResolver) {
        this.rootPath = rootPath;
        this.resolver = resolver;
        this._httpResolver = _httpResolver;
        this.listeners = [];
        this.tlisteners = [];
        this.pathToUnit = {};
        this.failedUnits = {};
        this._fsEnabled = true;
        this._namespaceResolver = new namespaceResolver.NamespaceResolver();
        if (this.resolver == null) {
            this.resolver = new FSResolverImpl();
        }
        else {
            this._fsEnabled = false;
        }
        if (this._httpResolver == null) {
            this._httpResolver = new HTTPResolverImpl();
        }
    }
    Project.prototype.getMainUnit = function () {
        if (!this.mainUnitPath) {
            return null;
        }
        return this.unit(this.mainUnitPath, true);
    };
    Project.prototype.getRootPath = function () {
        return this.rootPath;
    };
    Project.prototype.getMainUnitPath = function () {
        return this.mainUnitPath;
    };
    Project.prototype.setMainUnitPath = function (mainUnitPath) {
        this.mainUnitPath = mainUnitPath;
    };
    Project.prototype.setFSResolver = function (res) {
        this.resolver = res;
    };
    Project.prototype.setHTTPResolver = function (res) {
        this._httpResolver = res;
    };
    Project.prototype.fsEnabled = function () {
        return this._fsEnabled;
    };
    Project.prototype.cloneWithResolver = function (newResolver, httpResolver) {
        if (httpResolver === void 0) { httpResolver = null; }
        var newProject = new Project(this.rootPath, newResolver, httpResolver ? httpResolver : this._httpResolver);
        for (var unitPath in this.pathToUnit) {
            newProject.pathToUnit[unitPath] = this.pathToUnit[unitPath].cloneToProject(newProject);
        }
        return newProject;
    };
    Project.prototype.setCachedUnitContent = function (pth, cnt, tl) {
        if (tl === void 0) { tl = true; }
        var relPath = pth;
        var apath = lowlevel.toAbsolutePath(this.rootPath, pth);
        var unit = new CompilationUnit(relPath, cnt, tl, this, apath);
        this.pathToUnit[apath] = unit;
        return unit;
    };
    Project.prototype.resolveAsync = function (unitPath, pathInUnit) {
        var _this = this;
        if (!pathInUnit) {
            return Promise.reject(new Error(messageRegistry.UNIT_PATH_IS_NULL.message));
        }
        var includeReference = refResolvers.getIncludeReference(pathInUnit);
        var oldPath = pathInUnit;
        if (includeReference) {
            pathInUnit = includeReference.getIncludePath();
        }
        var absPath = lowlevel.buildPath(pathInUnit, unitPath, this.rootPath);
        if (includeReference) {
            var result;
            var refPath = lowlevel.toAbsolutePath(path.dirname(lowlevel.toAbsolutePath(this.rootPath, unitPath)), includeReference.encodedName());
            // if (this.pathToUnit[refPath]) {
            //     result = this.pathToUnit[refPath];
            // } else {
            //     this.pathToUnit[refPath] = new CompilationUnit(includeReference.encodedName(), refResolvers.resolveContents(oldPath), false, this, refPath);
            //
            //     result = this.pathToUnit[refPath];
            // }
            this.pathToUnit[absPath] ? Promise.resolve(result).then(function (unit) {
                _this.pathToUnit[refPath] = new CompilationUnit(includeReference.encodedName(), refResolvers.resolveContents(oldPath, _this.pathToUnit[absPath].contents()), false, _this, refPath);
                return _this.pathToUnit[refPath];
            }) : this.unitAsync(absPath, true).then(function (unit) {
                _this.pathToUnit[absPath] = unit;
                _this.pathToUnit[refPath] = new CompilationUnit(includeReference.encodedName(), refResolvers.resolveContents(oldPath, _this.pathToUnit[absPath].contents()), false, _this, refPath);
                return _this.pathToUnit[refPath];
            });
        }
        return this.unitAsync(absPath, true);
    };
    Project.prototype.resolve = function (unitPath, pathInUnit) {
        if (!pathInUnit) {
            return null;
        }
        pathInUnit = pathInUnit.replace(/\\/g, "/");
        var includeReference = refResolvers.getIncludeReference(pathInUnit);
        var oldPath = pathInUnit;
        if (includeReference) {
            pathInUnit = includeReference.getIncludePath();
        }
        var absPath = lowlevel.buildPath(pathInUnit, unitPath, this.rootPath);
        if (includeReference) {
            if (!this.pathToUnit[absPath]) {
                this.pathToUnit[absPath] = this.unit(absPath, true);
            }
            var wrappedUnit = this.pathToUnit[absPath];
            var refPath = lowlevel.toAbsolutePath(path.dirname(lowlevel.toAbsolutePath(this.rootPath, unitPath)), includeReference.encodedName());
            if (this.pathToUnit[refPath]) {
                return this.pathToUnit[refPath];
            }
            this.pathToUnit[refPath] = new CompilationUnit(includeReference.encodedName(), refResolvers.resolveContents(oldPath, wrappedUnit && wrappedUnit.contents()), false, this, refPath);
            return this.pathToUnit[refPath];
        }
        return this.unit(absPath, true);
    };
    Project.prototype.units = function () {
        var _this = this;
        if (!this.resolver.list) {
            throw new Error(messageRegistry.FSRESOLVER_IS_UNABLE_USE_EXTENDEDFSRESOLVER.message);
        }
        var names = this.resolver.list(this.rootPath).filter(function (x) { return path.extname(x) == '.raml'; });
        return names.map(function (x) { return _this.unit(x); }).filter(function (y) { return y.isTopLevel(); });
    };
    Project.prototype.unitsAsync = function () {
        var _this = this;
        if (!this.resolver.listAsync) {
            return Promise.reject(new Error(messageRegistry.FSRESOLVER_IS_UNABLE_USE_EXTENDEDFSRESOLVER.message));
        }
        return this.resolver.listAsync(this.rootPath).then(function (x) {
            var promises = x.filter(function (x) { return path.extname(x) == '.raml'; }).map(function (x) { return _this.unitAsync(x).then(function (x) {
                return x.isTopLevel() ? x : null;
            }, function (x) {
                return null;
            }); });
            return Promise.all(promises).then(function (arr) {
                return arr.filter(function (x) { return x != null; });
            });
        });
    };
    Project.prototype.lexerErrors = function () {
        var results = [];
        this.units().forEach(function (x) {
            results = results.concat(x.lexerErrors());
        });
        return results;
    };
    Project.prototype.deleteUnit = function (p, absolute) {
        if (absolute === void 0) { absolute = false; }
        var apath = null;
        if (lowlevel.isWebPath(p)) {
            apath = p;
        }
        else {
            apath = absolute ? p : lowlevel.toAbsolutePath(this.rootPath, p);
        }
        delete this.pathToUnit[apath];
    };
    Project.prototype.unit = function (p, absolute) {
        if (absolute === void 0) { absolute = false; }
        if (absolute || lowlevel.isWebPath(p)) {
            if (this.failedUnits[p] != null) {
                if (!this.failedUnits[p].inner) {
                    return null; //throw(this.failedUnits[p]);
                }
            }
        }
        else {
            var ap = lowlevel.toAbsolutePath(this.rootPath, p);
            if (this.failedUnits[ap]) {
                if (!this.failedUnits[p].inner) {
                    return null; //throw(this.failedUnits[p]);
                }
            }
        }
        var cnt = null;
        var apath = p;
        var response;
        if (lowlevel.isWebPath(p)) {
            if (this.pathToUnit[apath]) {
                return this.pathToUnit[apath];
            }
            if (this._httpResolver) {
                response = this._httpResolver.getResource(p);
                if (response && response.errorMessage) {
                    throw new Error(response.errorMessage);
                }
                if (response) {
                    cnt = response.content;
                }
                else {
                    cnt = null;
                }
            }
            else {
                response = new HTTPResolverImpl().getResource(apath);
                if (response) {
                    cnt = response.content;
                }
                else {
                    cnt = null;
                }
            }
        }
        else {
            if (p.charAt(0) == '/' && !absolute) {
                p = p.substr(1); //TODO REVIEW IT
            }
            var apath = lowlevel.toAbsolutePath(this.rootPath, p);
            if (this.pathToUnit[apath]) {
                return this.pathToUnit[apath];
            }
            if (lowlevel.isWebPath(apath)) {
                if (this._httpResolver) {
                    var resp = this._httpResolver.getResource(apath);
                    if (resp && resp.errorMessage) {
                        throw new Error(resp.errorMessage);
                    }
                    if (resp) {
                        cnt = resp.content;
                    }
                    else {
                        cnt = null;
                    }
                }
                else {
                    var resourceResponse = new HTTPResolverImpl().getResource(apath);
                    if (resourceResponse) {
                        cnt = resourceResponse.content;
                    }
                    else {
                        cnt = null;
                    }
                }
            }
            else {
                cnt = this.resolver.content(apath);
            }
        }
        if (cnt == null) {
            return null;
        }
        var tl = util.stringStartsWith(cnt, "#%RAML");
        var relPath = (lowlevel.isWebPath(this.rootPath) == lowlevel.isWebPath(apath)) ? path.relative(this.rootPath, apath) : apath;
        var unit = new CompilationUnit(relPath, cnt, tl, this, apath);
        this.pathToUnit[apath] = unit;
        if (response) {
            response.callback = function (contentHolder) {
                unit.updateContent(contentHolder && contentHolder.content);
            };
        }
        return unit;
    };
    Project.prototype.unitAsync = function (p, absolute) {
        var _this = this;
        if (absolute === void 0) { absolute = false; }
        var cnt = null;
        var apath = p;
        if (lowlevel.isWebPath(p)) {
            if (this.pathToUnit[apath]) {
                return Promise.resolve(this.pathToUnit[apath]);
            }
            if (this._httpResolver) {
                var resp = this._httpResolver.getResourceAsync(apath);
                cnt = resp.then(function (x) {
                    if (x.errorMessage) {
                        return Promise.reject(new Error(x.errorMessage));
                    }
                    return x.content;
                });
            }
            else {
                cnt = new HTTPResolverImpl().getResourceAsync(apath).then(function (x) {
                    if (x.errorMessage) {
                        return Promise.reject(x.errorMessage);
                    }
                    return x.content;
                });
            }
        }
        else {
            if (p.charAt(0) == '/' && !absolute) {
                p = p.substr(1); //TODO REVIEW IT
            }
            if (absolute) {
                apath = p;
            }
            else {
                apath = lowlevel.toAbsolutePath(this.rootPath, p);
            }
            if (this.pathToUnit[apath]) {
                return Promise.resolve(this.pathToUnit[apath]);
            }
            if (lowlevel.isWebPath(apath)) {
                if (this._httpResolver) {
                    var resp = this._httpResolver.getResourceAsync(apath);
                    cnt = resp.then(function (x) {
                        if (x.errorMessage) {
                            return Promise.reject(new Error(x.errorMessage));
                        }
                        return x.content;
                    });
                }
                else {
                    cnt = new HTTPResolverImpl().getResourceAsync(apath).then(function (x) {
                        if (x.errorMessage) {
                            return Promise.reject(new Error(x.errorMessage));
                        }
                        return x.content;
                    });
                }
            }
            else {
                cnt = this.resolver.contentAsync(apath);
            }
        }
        if (cnt == null) {
            return Promise.resolve(null);
        }
        var relPath = (lowlevel.isWebPath(this.rootPath) == lowlevel.isWebPath(apath)) ? path.relative(this.rootPath, apath) : apath;
        return cnt.then(function (x) {
            if (x == null) {
                return Promise.reject(new Error(linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE, { path: apath })));
            }
            var tl = util.stringStartsWith(x, "#%RAML");
            var unit = new CompilationUnit(relPath, x, tl, _this, apath);
            _this.pathToUnit[apath] = unit;
            return unit;
        }, function (err) {
            if (typeof (err) == "object" && err instanceof Error) {
                return Promise.reject(err);
            }
            else {
                return Promise.reject(new Error(err.toString()));
            }
        }).then(function (unit) {
            if (unit.isRAMLUnit()) {
                return unit;
            }
            return schemes.isScheme(unit.contents()) ? schemes.startDownloadingReferencesAsync(unit.contents(), unit) : unit;
        });
    };
    Project.prototype.visualizeNewlines = function (s) {
        var res = '';
        for (var i = 0; i < s.length; i++) {
            var ch = s[i];
            if (ch == '\r')
                ch = '\\r';
            if (ch == '\n')
                ch = '\\n';
            res += ch;
        }
        return res;
    };
    Project.prototype.indent = function (node) {
        //node.show('NODE');
        var text = node.unit().contents();
        //console.log('node text: ' + textutil.replaceNewlines(text.substring(node.start(), node.end())));
        //console.log('node parent: ' + node.parent());
        //console.log('node unit: ' + node.unit());
        if (node == node.root()) {
            //console.log('node is root');
            return '';
        }
        var leading = leadingIndent(node, text);
        //console.log('leading: [' + leading + '] ' + leading.length);
        var dmp = splitOnLines(node.dump());
        if (dmp.length > 1) {
            if (dmp[1].trim().length > 0) {
                //console.log('DMP0: [' + dmp[0] + ']');
                //console.log('DMP1: [' + dmp[1] + ']');
                var extra = indent(dmp[1]);
                return leading + extra;
            }
        }
        //console.log('LEADING: [' + this.visualizeNewlines(leading) + '] ');
        return leading + '  ';
    };
    Project.prototype.startIndent = function (node) {
        var text = node.unit().contents();
        //console.log('Node text:\n' + this.visualizeNewlines(text.substring(node.start(), node.end())));
        if (node == node.root())
            return '';
        var dmp = splitOnLines(node.dump());
        if (dmp.length > 0) {
            console.log('FIRST: ' + dmp[0]);
            var extra = indent(dmp[0]);
            return extra + '  ';
        }
        //console.log('LEADING: [' + this.visualizeNewlines(leading) + '] ');
        return '';
    };
    Project.prototype.canWriteInOneLine = function (node) {
        return false;
    };
    Project.prototype.isOneLine = function (node) {
        return node.text().indexOf('\n') < 0;
    };
    Project.prototype.recalcPositionsUp = function (target) {
        var np = target;
        while (np) {
            np.recalcEndPositionFromChilds();
            np = np.parent();
        }
    };
    Project.prototype.add2 = function (target, node, toSeq, ipoint, json) {
        if (json === void 0) { json = false; }
        var unit = target.unit();
        var api = target.root();
        //console.log('api: ' + api);
        var point = null;
        if (ipoint) {
            if (ASTNode.isInstance(ipoint)) {
                //console.log('insertion: ast node');
                point = ipoint;
            }
            if (InsertionPoint.isInstance(ipoint)) {
                //console.log('insertion: ip');
                point = ipoint.point;
            }
        }
        //console.log('target: ' + target.kindName() + '/' + target.valueKindName() + ' node: ' + node.kindName());
        //if(point) point.show('POINT:');
        if (target.isValueInclude()) {
            //console.log('insert to include ref');
            var childs = target.children();
            if (childs.length == 0) {
                throw new Error(messageRegistry.NOT_IMPLEMENTED_INSERT_INTO_EMPTY_REF.message);
            }
            var parent = childs[0].parent();
            //console.log('parent: ' + parent);
            //parent.show('INCLUDE PARENT:');
            this.add2(parent, node, toSeq, point, json);
            return;
        }
        var range = new textutil.TextRange(unit.contents(), node.start(), node.end());
        var targetRange = new textutil.TextRange(unit.contents(), target.start(), target.end());
        var unitText = target.unit().contents();
        if (target.valueKind() == yaml.Kind.SEQ) {
            target = createSeq(target.valueAsSeq(), target, target.unit());
        }
        var json = this.isJson(target);
        //console.log('target: ' + target.start() + '..' + target.end());
        var originalIndent = json ? '' : this.indent(target.isSeq() ? target.parent() : target);
        //console.log('indent: [' + originalIndent + '] ' + originalIndent.length + '; toseq: ' + toSeq + '; json: ' + json);
        var xindent = originalIndent;
        var indentLength = originalIndent.length;
        var isTargetSeq = target.isSeq() || target.isMapping() && (target.isValueSeq() || target.isValueScalar() || !target.asMapping().value); //target.valueKind() == yaml.Kind.SEQ || target.isSeq();
        //toSeq = false;
        //console.log('target: ' + target.kindName() + '/' + yaml.Kind[target.valueKind()] + '; toseq: ' + toSeq);
        //target.root().show("API:");
        //target.show("TARGET:");
        //console.log('oindent: ' + originalIndent.length);
        toSeq = toSeq; // || isTargetSeq;
        if (toSeq) {
            if (json) {
                // nothing
            }
            else {
                if (isTargetSeq) {
                    xindent += "  ";
                    indentLength += 2;
                }
            }
        }
        //console.log('xindent: ' + xindent.length);
        var buf = new MarkupIndentingBuffer(xindent);
        //target.show('TARGET:');
        //node.show('NODE1');
        node.markupNode(buf, node._actualNode(), 0, json);
        var text = buf.text;
        //node.show('NODE2', 0, text);
        //console.log('TEXT TO ADD0: ' + textutil.replaceNewlines(text));
        if (toSeq) {
            //if(target.valueKind() == yaml.Kind.SEQ) {
            var trimText = textutil.trimEnd(text);
            var trimLen = text.length - trimText.length;
            if (trimLen > 0) {
                //console.log('trim len: ' + trimLen);
                var textlen = text.length;
                text = text.substring(0, textlen - trimLen);
                node.shiftNodes(textlen - trimLen, -trimLen);
                //node.show('NODE SHIFTED', 0, text);
            }
            //}
        }
        //target.show('TARGET2');
        //node.show('NODE2', 0, text);
        //console.log('TEXT TO ADD1: ' + textutil.replaceNewlines(text));
        //console.log('TEXT TO ADD:\n' + this.visualizeNewlines(text));
        //console.log('toseq: ' + toSeq);
        if (toSeq && !json) {
            if (node.highLevelNode()) {
                //console.log('embedmap: ' + node.highLevelNode().property().isEmbedMap());
            }
            //console.log('target: ' + target.kindName());
            if (target.isMapping()) {
                //console.log('target value: ' + yaml.Kind[target.valueKind()]);
            }
            if (target.isSeq() || target.isMapping() && (target.isValueSeq() || target.isValueScalar() || !target.asMapping().value)) {
                //console.log('--- make it seq');
                text = originalIndent + '- ' + text;
            }
            else {
                //console.log('--- keep it map');
                text = originalIndent + text;
            }
        }
        else {
            text = originalIndent + text;
        }
        //console.log('TEXT TO ADD2: ' + textutil.replaceNewlines(text));
        //target.show('TARGET3');
        var pos = target.end();
        //console.log('insert to target end: ' + pos+ ' ; point: ' + point);
        if (point) {
            //point.show("POINT");
            if (point != target) {
                pos = point.end();
            }
            else {
                if (json && toSeq) {
                    //
                }
                else {
                    pos = target.keyEnd() + 1;
                    pos = new textutil.TextRange(unitText, pos, pos).extendAnyUntilNewLines().endpos();
                }
            }
        }
        else {
            if (json && toSeq) {
                var seq = target.asSeq();
                if (seq) {
                    if (seq.items.length > 0) {
                        pos = seq.items[seq.items.length - 1].endPosition;
                        //console.log('indert to last end: ' + pos);
                    }
                    else {
                        pos = seq.endPosition - 1;
                        //console.log('indert to empty: ' + pos);
                    }
                }
            }
            else {
                if (ipoint && (InsertionPoint.isInstance(ipoint))) {
                    //ipoint.show('insertion point provided');
                    var ip = ipoint;
                    if (ip.type == InsertionPointType.START) {
                        pos = target.keyEnd() + 1;
                        pos = new textutil.TextRange(unitText, pos, pos).extendAnyUntilNewLines().endpos();
                    }
                }
            }
        }
        //console.log('insert poition: ' + pos);
        var insertionRange = new textutil.TextRange(unitText, 0, pos);
        pos = insertionRange.extendToNewlines().reduceSpaces().endpos();
        if (json && target.isSeq()) {
            var seq = target.asSeq();
            if (seq.items.length > 0) {
                text = ', ' + text;
                indentLength += 2;
            }
        }
        else if (pos > 0 && unitText[pos - 1] != '\n') {
            text = "\n" + text;
            indentLength++;
        }
        var suffixLen = 0;
        if (toSeq && !json) {
            text += '\n';
            suffixLen++;
        }
        //console.log('FINAL TEXT TO ADD: [' + textutil.replaceNewlines(text) + '] at position ' + pos);
        var newtext = unitText.substring(0, pos) + text + unitText.substring(pos, unitText.length);
        var cu = unit;
        cu.updateContentSafe(newtext);
        this.executeReplace(new textutil.TextRange(unitText, pos, pos), text, cu);
        //console.log('shift root from position: ' + pos);
        target.root().shiftNodes(pos, indentLength + (node.end() - node.start()) + suffixLen);
        //console.log('node len: ' + (node.end()-node.start()));
        //console.log('text len: ' + text.length);
        //(<ASTNode>target.root()).shiftNodes(pos, text.length+indentLength);
        //target.show('TARGET2:');
        //node.show('NODE TO ADD:');
        if (point) {
            var childs = target.children();
            var index = -1;
            for (var i = 0; i < childs.length; i++) {
                var x = childs[i];
                if (x.start() == point.start() && x.end() == point.end()) {
                    index = i;
                    break;
                }
            }
            //console.log('index: ' + index);
            if (index >= 0) {
                target.addChild(node, index + 1);
            }
            else {
                target.addChild(node);
            }
        }
        else {
            target.addChild(node);
        }
        node.shiftNodes(0, pos + indentLength);
        //target.show('TARGET UPDATED:');
        this.recalcPositionsUp(target);
        //target.show('TARGET UPDATED POSITIONS:');
        //api.show('ROOT UPDATED POSITIONS:');
        node.setUnit(target.unit());
        node.visit(function (n) {
            var node = n;
            node.setUnit(target.unit());
            return true;
        });
    };
    Project.prototype.isJsonMap = function (node) {
        if (!node.isMap())
            return false;
        var text = node.text().trim();
        return text.length >= 2 && text[0] == '{' && text[text.length - 1] == '}';
    };
    Project.prototype.isJsonSeq = function (node) {
        if (!node.isSeq())
            return false;
        var text = node.text().trim();
        return text.length >= 2 && text[0] == '[' && text[text.length - 1] == ']';
    };
    Project.prototype.isJson = function (node) {
        return this.isJsonMap(node) || this.isJsonSeq(node);
    };
    Project.prototype.remove = function (unit, target, node) {
        var parent = node.parent();
        node._oldText = node.dump();
        //node.showParents('PARENTS:');
        //console.log('REMOVE NODE: ' + node.kindName() + ' from ' + target.kindName());
        //console.log('INITIAL SELECTION: [' + textutil.replaceNewlines(range.text()) + ']');
        //console.log('  text: \n' + unitText.substring(startpos,endpos));
        if (this.isOneLine(node) && node.isMapping() && node.parent().isMap()) {
            var mapnode = node.parent();
            if (mapnode.asMap().mappings.length == 1 && mapnode.parent() != null) {
                //console.log('REMOVE MAP INSTEAD!');
                this.remove(unit, mapnode.parent(), mapnode);
                return;
            }
        }
        if (this.isOneLine(node) && node.isScalar() && node.parent().isSeq()) {
            var seqnode = node.parent();
            var seqn = seqnode.asSeq();
            //console.log('SEQ: ' + seqn.items.length);
            if (seqn.items.length == 1) {
                //console.log('REMOVE SEQ INSTEAD!');
                this.remove(unit, seqnode.parent(), seqnode);
                return;
            }
        }
        if (target.isMapping() && node.isSeq()) {
            //console.log('remove seq from mapping');
            var map = target.parent();
            //console.log('REMOVE MAPPING INSTEAD!');
            this.remove(unit, map, target);
            return;
        }
        //target.show('TARGET:');
        //node.show('NODE:');
        var range = new textutil.TextRange(unit.contents(), node.start(), node.end());
        var targetRange = new textutil.TextRange(unit.contents(), target.start(), target.end());
        var parentRange = new textutil.TextRange(unit.contents(), parent.start(), parent.end());
        var originalStartPos = range.startpos();
        //console.log('REMOVE TEXT: ' +  this.visualizeNewlines(range.text()));
        if (target.isSeq()) {
            // extend range to start of line
            //console.log('RANGE SEQ 0: ' + textutil.replaceNewlines(range.text()));
            var seq = (node.isSeq() ? node : node.parentOfKind(yaml.Kind.SEQ));
            //console.log('seq: ' + seq.text() + ' json: ' + this.isJson(seq));
            if (seq && this.isJson(seq)) {
                range = range.extendSpaces().extendCharIfAny(',').extendSpaces();
            }
            else {
                range = range.extendToStartOfLine().extendAnyUntilNewLines().extendToNewlines(); //
            }
            //console.log('RANGE SEQ 1:\n-----------\n' + range.text() + '\n-------------');
        }
        if (target.isMap()) {
            // extend range to end of line
            //console.log('RANGE MAP 0: [' +  this.visualizeNewlines(range.text()) + ']');
            range = range.trimEnd().extendAnyUntilNewLines().extendToNewlines();
            //console.log('RANGE MAP 1: [' +  this.visualizeNewlines(range.text()) + ']');
            range = range.extendToStartOfLine().extendUntilNewlinesBack();
            //console.log('RANGE MAP 2: [' +  this.visualizeNewlines(range.text()) + ']');
        }
        if (target.kind() == yaml.Kind.MAPPING) {
            //console.log('RANGE MAPPING 0: ' +  this.visualizeNewlines(range.text()));
            //console.log('NODE TEXT: ' + node.text());
            if (this.isJson(node) && this.isOneLine(node)) {
                // no need to trim trailing new lines
            }
            else {
                // extend range to end of line
                //console.log('RANGE MAP 0: ' +  this.visualizeNewlines(range.text()));
                range = range.extendSpacesUntilNewLines();
                range = range.extendToNewlines();
                //console.log('RANGE MAP 2: ' +  this.visualizeNewlines(range.text()));
                range = range.extendToStartOfLine().extendUntilNewlinesBack();
                //console.log('RANGE MAP 3: ' +  this.visualizeNewlines(range.text()));
            }
            //console.log('RANGE MAPPING 1: ' +  this.visualizeNewlines(range.text()));
        }
        if (node.isSeq()) {
            //console.log('cleanup seq');
            range = range.reduceSpaces();
        }
        //console.log('NODE:\n-----------\n' + range.unitText() + '\n-------------');
        //console.log('TARGET: ' + target.kindName());
        //target.show('TARGET');
        //console.log('FINAL REMOVE TEXT: [' +  this.visualizeNewlines(range.text()) + ']');
        //console.log('NEW TEXT:\n-----------\n' + range.remove() + '\n-------------');
        var cu = unit;
        cu.updateContentSafe(range.remove());
        this.executeReplace(range, "", cu);
        //node.parent().show('Before remove');
        node.parent().removeChild(node);
        var shift = -range.len();
        //console.log('shift: ' + shift);
        target.root().shiftNodes(originalStartPos, shift);
        this.recalcPositionsUp(target);
        //this.executeTextChange(new lowlevel.TextChangeCommand(range.startpos(), range.len(), "", unit))
        //target.show('TARGET AFTER REMOVE:');
        //target.root().show('API AFTER REMOVE:');
    };
    Project.prototype.changeKey = function (unit, attr, newval) {
        //console.log('set key: ' + newval);
        var range = new textutil.TextRange(attr.unit().contents(), attr.keyStart(), attr.keyEnd());
        if (attr.kind() == yaml.Kind.MAPPING) {
            var sc = attr._actualNode().key;
            sc.value = newval;
            sc.endPosition = sc.startPosition + newval.length;
        }
        var cu = unit;
        this.executeReplace(range, newval, cu);
        //console.log('new text: ' + this.visualizeNewlines(newtext));
        var shift = newval.length - range.len();
        //console.log('shift: ' + shift);
        attr.root().shiftNodes(range.startpos(), shift, attr);
        this.recalcPositionsUp(attr);
    };
    Project.prototype.executeReplace = function (r, txt, unit) {
        var command = new lowlevel.TextChangeCommand(r.startpos(), r.endpos() - r.startpos(), txt, unit);
        unit.project();
        try {
            this.tlisteners.forEach(function (x) { return x(command); });
        }
        catch (e) {
            return false;
        }
        var newtext = r.replace(txt);
        unit.updateContentSafe(newtext);
        return true;
    };
    Project.prototype.changeValue = function (unit, attr, newval) {
        //console.log('set value: ' + newval);mark
        //console.log('ATTR ' + yaml.Kind[attr.kind()] + '; VALUE: ' + val + ' => ' + newval);
        //attr.root().show('NODE:');
        //console.log('TEXT:\n' + attr.unit().contents());
        var range = new textutil.TextRange(attr.unit().contents(), attr.start(), attr.end());
        //console.log('Range0: ' + range.startpos() + '..' + range.endpos() + ': [' + this.visualizeNewlines(range.text()) + ']');
        //console.log('ATTR: ' + attr.kindName());
        //attr.root().show('BEFORE');
        var newNodeText;
        var prefix = 0;
        var delta = 0;
        var replacer = null;
        var mapping = null;
        //console.log('attr: ' + attr.kindName());
        if (attr.kind() == yaml.Kind.SCALAR) {
            if (typeof newval == 'string') {
                attr.asScalar().value = newval;
                //range = range.withStart(attr.valueStart()).withEnd(attr.valueEnd());
                //console.log('Range1: ' + this.visualizeNewlines(range.text()));
                //console.log('Range0: ' + range.startpos() + '..' + range.endpos());
                newNodeText = newval;
            }
            else {
                throw new Error(messageRegistry.NOT_IMPLEMENTED.message);
            }
        }
        else if (attr.kind() == yaml.Kind.MAPPING) {
            //attr.show('ATTR:');
            mapping = attr.asMapping();
            //console.log('mapping val: ' + attr.valueKindName());
            if (attr.isValueInclude()) {
                var inc = attr.valueAsInclude();
                var includeString = inc.value;
                var includePath = includeString;
                //console.log("attr.setValue: path: " + includePath);
                var resolved = attr.unit().resolve(includePath);
                if (resolved == null) {
                    console.log(linter.applyTemplate(messageRegistry.ATTR_SETVALUE_NOT_RESOLVE, { path: includePath }));
                    return; // "can not resolve "+includePath
                }
                //console.log("attr.setValue: resolved: " + includePath);
                if (resolved.isRAMLUnit()) {
                    //TODO DIFFERENT DATA TYPES, inner references
                    return;
                }
                //TODO for now disabling an update from outline details to JSON schema when there is a reference
                //to an inner element of the schema
                if (!refResolvers.getIncludeReference(includeString)) {
                    resolved.updateContent(newval);
                }
                return;
            }
            //console.log('Range0: ' + range.startpos() + '..' + range.endpos() + ': [' + this.visualizeNewlines(range.text()) + ']');
            if (mapping.value)
                range = range.withStart(attr.valueStart()).withEnd(attr.valueEnd());
            else
                range = range.withStart(attr.keyEnd() + 1).withEnd(attr.keyEnd() + 1);
            //console.log('Range1: ' + range.startpos() + '..' + range.endpos());
            range = range.reduceNewlinesEnd();
            //console.log('Range2: ' + range.startpos() + '..' + range.endpos() + ': [' + this.visualizeNewlines(range.text()) + ']');
            if (newval == null) {
                newNodeText = '';
                mapping.value = null;
            }
            else if (typeof newval == 'string' || newval == null) {
                var newstr = newval;
                var ind = this.indent(attr);
                //console.log('indent: ' + ind.length);
                if (newstr && textutil.isMultiLine(newstr)) {
                    newstr = '' + textutil.makeMutiLine(newstr, ind.length / 2);
                }
                newNodeText = newstr;
                //var valueNode = null;
                if (!mapping.value) {
                    console.log('no value');
                    mapping.value = yaml.newScalar(newstr);
                    mapping.value.startPosition = attr.keyEnd() + 1;
                    mapping.value.endPosition = mapping.value.startPosition + newstr.length;
                    mapping.endPosition = mapping.value.endPosition;
                    if (unit.contents().length > attr.keyEnd() + 1) {
                        var vlPos = attr.keyEnd() + 1;
                        if (unit.contents()[vlPos - 1] == ':') {
                            newNodeText = " " + newNodeText;
                            mapping.value.startPosition++;
                            mapping.value.endPosition++;
                            mapping.endPosition++;
                            delta++;
                        }
                    }
                }
                else if (mapping.value.kind == yaml.Kind.SEQ) {
                    console.log('seq value');
                    var v = mapping.value.items[0];
                    //TODO !!! assign value
                    throw "assign value!!!";
                }
                else if (mapping.value.kind == yaml.Kind.SCALAR) {
                    //console.log('scalar value');
                    var sc = mapping.value;
                    var oldtext = sc.value || "";
                    //console.log('oldval: ' + sc.value);
                    //console.log('newstr: ' + newstr + ' ' + newstr.length);
                    sc.value = newstr;
                    //console.log('value1: ' + mapping.value.startPosition + '..' + mapping.value.endPosition);
                    mapping.value.endPosition = mapping.value.startPosition + newstr.length;
                    //console.log('value2: ' + mapping.value.startPosition + '..' + mapping.value.endPosition);
                    mapping.endPosition = mapping.value.endPosition;
                    //console.log('mvalue: ' + mapping.startPosition + '..' + mapping.endPosition);
                    //console.log('newval: ' + sc.value);
                    delta += newstr.length - oldtext.length;
                    //attr._children = null;
                }
                //console.log('newtext: ' + this.visualizeNewlines(newstr));
                //console.log('Range1: ' + range.startpos() + '..' + range.endpos() + ': ' + this.visualizeNewlines(range.text()));
                //console.log('set mapping scalar/seq: to: ' + newstr);
                //attr.show('ATTR1:');
            }
            else {
                var n = newval;
                if (n.isMapping()) {
                    newval = createMap([n.asMapping()]);
                    n = newval;
                }
                else if (n.isMap()) {
                    // nothing
                }
                else {
                    throw new Error(messageRegistry.ONLY_MAP_NODES_ALLOWED.message);
                }
                //n.show('NODE1');
                var buf = new MarkupIndentingBuffer('');
                n.markupNode(buf, n._actualNode(), 0, true);
                //n.show('NODE2');
                newNodeText = '' + buf.text + '';
                //indent++;
                //n.shiftNodes(0, 1);
                //console.log('node text: [[[' + newNodeText + ']]]');
                //n.show("NN1:", 0, newNodeText);
                //range = mapping.value? range.withStart(attr.valueStart()).withEnd(attr.valueEnd()) : range.withStart(attr.keyEnd()+1).withEnd(attr.keyEnd()+1 + newNodeText);
                n.shiftNodes(0, range.startpos() + delta);
                //n.show("NN2:");
                replacer = n;
                //console.log('new node text: ' + this.visualizeNewlines(newNodeText) + '; len: ' + newNodeText.length);
            }
        }
        else {
            console.log(linter.applyTemplate(messageRegistry.UNSUPPORTED_CHANGE_VALUE_CASE, { name: attr.kindName() }));
        }
        //console.log('RangeX: ' + range.startpos() + '..' + range.endpos() + ': [' + this.visualizeNewlines(range.text()) + ']');
        //console.log('new node text: ' + newNodeText);
        var cu = unit;
        //console.log('Range1: ' + range.startpos() + '..' + range.endpos());
        //console.log('replace: ' + range.len());
        //console.log('Range: ' + range.startpos() + '..' + range.endpos());
        //console.log('OldText: ' + this.visualizeNewlines(cu.contents()));
        this.executeReplace(range, newNodeText, cu);
        //var newtext = range.replace(newNodeText);
        //console.log('NewText: ' + this.visualizeNewlines(newtext));
        //cu.updateContentSafe(newtext);
        var shift = newNodeText.length - range.len();
        //var shift = delta;
        //attr.root().show('BEFORE SHIFT');
        //console.log('shift: ' + shift + '; from: ' + (range.endpos() + prefix) + '; delta: ' + delta + '; prefix: ' + prefix);
        attr.root().shiftNodes(range.endpos() + prefix, shift, attr);
        //(<ASTNode>attr.root()).shiftNodes(range.endpos()+indent, shift);
        //attr.show('ATTR2:');
        if (replacer) {
            mapping.value = replacer._actualNode();
        }
        this.recalcPositionsUp(attr);
    };
    Project.prototype.initWithRoot = function (root, newroot) {
        var shift = root.end();
        newroot.markup(false);
        newroot._actualNode().startPosition = shift;
        newroot._actualNode().endPosition = shift;
        newroot.setUnit(root.unit());
    };
    Project.prototype.execute = function (cmd) {
        var _this = this;
        //console.log('Commands: ' + cmd.commands.length);
        cmd.commands.forEach(function (x) {
            //console.log('EXECUTE: kind: ' + lowlevel.CommandKind[x.kind] + '; val: ' + x.value);
            switch (x.kind) {
                case lowlevel.CommandKind.CHANGE_VALUE:
                    var attr = x.target;
                    var curval = attr.value();
                    if (!curval) {
                        curval = "";
                    }
                    var newval = x.value;
                    console.log('set value: ' + (typeof curval) + ' ==> ' + (typeof newval));
                    if ((typeof (curval) == 'string' ||
                        typeof (curval) == 'number' ||
                        typeof (curval) == 'boolean') && typeof newval == 'string') {
                        //console.log('set value: str => str');
                        if (curval != newval) {
                            _this.changeValue(attr.unit(), attr, newval);
                        }
                    }
                    else if ((typeof (curval) == 'string' ||
                        typeof (curval) == 'number' ||
                        typeof (curval) == 'boolean')
                        && typeof (newval) != 'string') {
                        //console.log('set value: str => obj');
                        // change structure
                        //this.changeValue(attr.unit(), attr, null);
                        _this.changeValue(attr.unit(), attr, newval);
                    }
                    else if (typeof curval != 'string' && typeof newval == 'string') {
                        var newstr = x.value;
                        if (curval.kind() == yaml.Kind.MAPPING) {
                            if (textutil.isMultiLine(newstr)) {
                                //console.log('multiline');
                                attr.children().forEach(function (n) {
                                    _this.remove(attr.unit(), attr, n);
                                });
                                _this.changeValue(attr.unit(), attr, newstr);
                            }
                            else {
                                //console.log('singleline');
                                _this.changeKey(attr.unit(), curval, newstr);
                            }
                        }
                        else {
                            throw new Error(linter.applyTemplate(messageRegistry.UNSUPPORTED_CASE_ATTRIBUTE_VALUE_CONVERSION, { curval: curval, newval: newval }));
                        }
                    }
                    else if (typeof curval != 'string' && typeof newval != 'string') {
                        var newvalnode = newval;
                        //(<ASTNode>curval).show("OLD:");
                        //newvalnode.show("NEW:");
                        if (newvalnode.isMapping()) {
                            newval = createMap([newvalnode.asMapping()]);
                            //(<ASTNode>newval).show("NEW2:");
                        }
                        //console.log('obj obj: ' + (curval == newval));
                        if (curval == newval)
                            break;
                        // change structure
                        //console.log('set value: obj => obj');
                        var node = newval;
                        var map = node.asMap();
                        //console.log('attr: ' + attr.kindName() + " " + attr.dump());
                        attr.children().forEach(function (n) {
                            _this.remove(attr.unit(), attr, n);
                        });
                        node.children().forEach(function (m) {
                            //this.add2(attr, <ASTNode>m, false, null, true);
                        });
                        _this.changeValue(attr.unit(), attr, newval);
                    }
                    else {
                        throw new Error(linter.applyTemplate(messageRegistry.UNSUPPORTED_CASE_ATTRIBUTE_VALUE_CONVERSION, { curval: curval, newval: newval }));
                    }
                    return;
                case lowlevel.CommandKind.CHANGE_KEY:
                    var attr = x.target;
                    _this.changeKey(attr.unit(), attr, x.value);
                    return;
                case lowlevel.CommandKind.ADD_CHILD:
                    var attr = x.target;
                    var newValueNode = x.value;
                    _this.add2(attr, newValueNode, x.toSeq, x.insertionPoint);
                    return;
                case lowlevel.CommandKind.REMOVE_CHILD:
                    var target = x.target;
                    var node = x.value;
                    _this.remove(target.unit(), target, node);
                    return;
                case lowlevel.CommandKind.INIT_RAML_FILE:
                    var root = x.target;
                    var newroot = x.value;
                    _this.initWithRoot(root, newroot);
                    return;
                default:
                    console.log(linter.applyTemplate(messageRegistry.UNSUPPORTED_COMMAND, { name: lowlevel.CommandKind[x.kind] }));
                    return;
            }
        });
    };
    Project.prototype.replaceYamlNode = function (target, newNodeContent, offset, shift, unit) {
        //console.log('New content:\n' + newNodeContent);
        //target.show('OLD TARGET');
        var newYamlNode = yaml.load(newNodeContent, { ignoreDuplicateKeys: true });
        //console.log('new yaml: ' + yaml.Kind[newYamlNode.kind]);
        this.updatePositions(target.start(), newYamlNode);
        //console.log('Shift: ' + shift);
        //(<ASTNode>unit.ast()).shiftNodes(offset, shift);
        target.root().shiftNodes(offset, shift);
        var targetParent = target.parent();
        var targetYamlNode = target._actualNode();
        var parent = targetYamlNode.parent;
        newYamlNode.parent = parent;
        if (targetParent && targetParent.kind() == yaml.Kind.MAP) {
            //console.log('MAP!!!');
            var targetParentMapNode = targetParent._actualNode();
            targetParentMapNode.mappings = targetParentMapNode.mappings.map(function (x) {
                if (x != targetYamlNode) {
                    return x;
                }
                return newYamlNode;
            });
        }
        target.updateFrom(newYamlNode);
        //target.show('MEW TARGET');
        this.recalcPositionsUp(target);
    };
    Project.prototype.executeTextChange2 = function (textCommand) {
        var cu = textCommand.unit;
        var unitText = cu.contents();
        var target = textCommand.target;
        if (target) {
            var cnt = unitText.substring(target.start(), target.end());
            var original = unitText;
            unitText = unitText.substr(0, textCommand.offset) + textCommand.text + unitText.substr(textCommand.offset + textCommand.replacementLength);
            var newNodeContent = cnt.substr(0, textCommand.offset - target.start()) +
                textCommand.text + cnt.substr(textCommand.offset - target.start() + textCommand.replacementLength);
            cu.updateContentSafe(unitText);
            if (textCommand.offset > target.start()) {
                try {
                    var shift = textCommand.text.length - textCommand.replacementLength;
                    var offset = textCommand.offset;
                    target.unit().project().replaceYamlNode(target, newNodeContent, offset, shift, textCommand.unit);
                }
                catch (e) {
                    console.log('New node contents (causes error below): \n' + newNodeContent);
                    console.log('Reparse error: ' + e.stack);
                }
            }
        }
        else {
            unitText = unitText.substr(0, textCommand.offset) + textCommand.text + unitText.substr(textCommand.offset + textCommand.replacementLength);
        }
        cu.updateContent(unitText);
        this.listeners.forEach(function (x) {
            x(null);
        });
        this.tlisteners.forEach(function (x) {
            x(textCommand);
        });
    };
    Project.prototype.executeTextChange = function (textCommand) {
        var l0 = new Date().getTime();
        try {
            var oc = textCommand.unit.contents();
            //console.log('Offset: ' + textCommand.offset + '; end: ' + (textCommand.offset + textCommand.replacementLength) + '; len: ' + textCommand.replacementLength);
            var target = textCommand.target;
            if (target == null) {
                target = this.findNode(textCommand.unit.ast(), textCommand.offset, textCommand.offset + textCommand.replacementLength);
            }
            var cu = textCommand.unit;
            if (target) {
                var cnt = oc.substring(target.start(), target.end());
                //console.log('Content: ' + cnt);
                var original = oc;
                oc = oc.substr(0, textCommand.offset) + textCommand.text + oc.substr(textCommand.offset + textCommand.replacementLength);
                var newNodeContent = cnt.substr(0, textCommand.offset - target.start()) +
                    textCommand.text + cnt.substr(textCommand.offset - target.start() + textCommand.replacementLength);
                cu.updateContentSafe(oc);
                //console.log('UPDATED TEXT: ' + oc);
                var hasNewLines = breaksTheLine(original, textCommand);
                if (textCommand.offset > target.start()) {
                    //we can just reparse new node content;
                    //console.log(newNodeContent)
                    try {
                        var newYamlNode = yaml.load(newNodeContent, { ignoreDuplicateKeys: true });
                        this.updatePositions(target.start(), newYamlNode);
                        //console.log("Positions updated")
                        //lets shift all after it
                        var shift = textCommand.text.length - textCommand.replacementLength;
                        //console.log('shift: ' + shift);
                        //console.log('offset: ' + textCommand.offset);
                        textCommand.unit.ast().shiftNodes(textCommand.offset, shift);
                        //console.log('Unit AST: ' + textCommand.unit.ast())
                        if (newYamlNode != null && newYamlNode.kind == yaml.Kind.MAP) {
                            var actualResult = newYamlNode.mappings[0];
                            var targetYamlNode = target._actualNode();
                            var parent = targetYamlNode.parent;
                            var cmd = new lowlevel.ASTDelta();
                            var unit = textCommand.unit;
                            cmd.commands = [
                                new lowlevel.ASTChangeCommand(lowlevel.CommandKind.CHANGE_VALUE, new ASTNode(copyNode(targetYamlNode), unit, null, null, null), new ASTNode(actualResult, unit, null, null, null), 0)
                            ];
                            if (parent && parent.kind == yaml.Kind.MAP) {
                                var map = parent;
                                map.mappings = map.mappings.map(function (x) {
                                    if (x != targetYamlNode) {
                                        return x;
                                    }
                                    return actualResult;
                                });
                            }
                            actualResult.parent = parent;
                            //updating low level ast from yaml
                            this.recalcPositionsUp(target);
                            target.updateFrom(actualResult);
                            //console.log("Incremental without listeners: "+(new Date().getTime()-l0));
                            //console.log("Notify listeners1: " + this.listeners.length + ":" + this.tlisteners.length);
                            this.listeners.forEach(function (x) {
                                x(cmd);
                            });
                            this.tlisteners.forEach(function (x) {
                                x(textCommand);
                            });
                            //console.log("Incremental update processed");
                            return;
                        }
                    }
                    catch (e) {
                        console.log(linter.applyTemplate(messageRegistry.NEW_NODE_CONTENTS_ERROR_BELOW, { content: newNodeContent }));
                        console.log(linter.applyTemplate(messageRegistry.REPARSE_ERROR, { content: e.stack }));
                    }
                }
            }
            else {
                oc = oc.substr(0, textCommand.offset) + textCommand.text + oc.substr(textCommand.offset + textCommand.replacementLength);
            }
            var t2 = new Date().getTime();
            //console.log("Full without listeners:"+(t2-l0));
            //!find node in scope
            cu.updateContent(oc);
            //console.log("Notify listeners2: " + this.listeners.length + ":" + this.tlisteners.length);
            this.listeners.forEach(function (x) {
                x(null);
            });
            this.tlisteners.forEach(function (x) {
                x(textCommand);
            });
        }
        finally {
            var t2 = new Date().getTime();
            //console.log("Total:"+(t2-l0));
        }
    };
    Project.prototype.updatePositions = function (offset, n) {
        var _this = this;
        if (n == null) {
            return;
        }
        if (n.startPosition == -1) {
            n.startPosition = offset;
        }
        else {
            n.startPosition = offset + n.startPosition;
        }
        n.endPosition = offset + n.endPosition;
        //console.log('SET POS: ' + n.startPosition + ".." + n.endPosition);
        switch (n.kind) {
            case yaml.Kind.MAP:
                var m = n;
                m.mappings.forEach(function (x) { return _this.updatePositions(offset, x); });
                break;
            case yaml.Kind.MAPPING:
                var ma = n;
                this.updatePositions(offset, ma.key);
                this.updatePositions(offset, ma.value);
                break;
            case yaml.Kind.SCALAR:
                break;
            case yaml.Kind.SEQ:
                var s = n;
                s.items.forEach(function (x) { return _this.updatePositions(offset, x); });
                break;
        }
    };
    Project.prototype.findNode = function (n, offset, end) {
        var _this = this;
        if (n == null) {
            return null;
        }
        var node = n;
        if (n.start() <= offset && n.end() >= end) {
            var res = n;
            node.directChildren().forEach(function (x) {
                var m = _this.findNode(x, offset, end);
                if (m) {
                    res = m;
                }
            });
            return res;
        }
        return null;
    };
    //shiftNodes(n:lowlevel.ILowLevelASTNode, offset:number, shift:number):lowlevel.ILowLevelASTNode{
    //    var node:ASTNode=<ASTNode>n;
    //    if (node==null){
    //        return null;
    //    }
    //    node.directChildren().forEach(x=> {
    //        var m = this.shiftNodes(x, offset, shift);
    //    })
    //    var yaNode=(<ASTNode>n)._actualNode();
    //    if(yaNode) innerShift(offset, yaNode, shift);
    //    return null;
    //}
    Project.prototype.addTextChangeListener = function (listener) {
        this.tlisteners.push(listener);
    };
    Project.prototype.removeTextChangeListener = function (listener) {
        this.tlisteners = this.tlisteners.filter(function (x) { return x != listener; });
    };
    Project.prototype.addListener = function (listener) {
        this.listeners.push(listener);
    };
    Project.prototype.removeListener = function (listener) {
        this.listeners = this.listeners.filter(function (x) { return x != listener; });
    };
    Project.prototype.namespaceResolver = function () {
        return this._namespaceResolver;
    };
    return Project;
}());
exports.Project = Project;
function breaksTheLine(oc, textCommand) {
    var oldText = oc.substr(textCommand.offset, textCommand.replacementLength);
    if (oldText.indexOf('\n') != -1) {
        return true;
    }
    if (textCommand.text.indexOf('\n') != -1) {
        return true;
    }
}
function tryParseScalar(q) {
    if (q == "null") {
        q = null;
    }
    else if (q == "~") {
        q = null;
    }
    else if (q == "true") {
        q = true;
    }
    else if (q == "false") {
        q = false;
    }
    else {
        var vl = parseFloat(q);
        if (!isNaN(vl)) {
            if (("" + q).match("^[-+]?[0-9]*\\.?[0-9]+$")) {
                q = vl;
            }
        }
    }
    return q;
}
var ASTNode = /** @class */ (function () {
    function ASTNode(_node, _unit, _parent, _anchor, _include, cacheChildren, _includesContents) {
        if (cacheChildren === void 0) { cacheChildren = false; }
        if (_includesContents === void 0) { _includesContents = false; }
        this._node = _node;
        this._unit = _unit;
        this._parent = _parent;
        this._anchor = _anchor;
        this._include = _include;
        this.cacheChildren = cacheChildren;
        this._includesContents = _includesContents;
        this._errors = [];
    }
    ASTNode.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), ASTNode.CLASS_IDENTIFIER);
    };
    ASTNode.prototype.getClassIdentifier = function () {
        var superIdentifiers = [];
        return superIdentifiers.concat(ASTNode.CLASS_IDENTIFIER);
    };
    ASTNode.prototype.actual = function () {
        return this._node;
    };
    ASTNode.prototype.yamlNode = function () {
        return this._node;
    };
    ASTNode.prototype.includesContents = function () {
        return this._includesContents;
    };
    ASTNode.prototype.setIncludesContents = function (includesContents) {
        this._includesContents = includesContents;
    };
    ASTNode.prototype.gatherIncludes = function (s, inc, anc, inOneMemberMap) {
        var _this = this;
        if (s === void 0) { s = []; }
        if (inc === void 0) { inc = null; }
        if (anc === void 0) { anc = null; }
        if (inOneMemberMap === void 0) { inOneMemberMap = true; }
        if (this._node == null) {
            return; //TODO FIXME
        }
        var kind = this._node.kind;
        if (kind == yaml.Kind.SCALAR) {
            if (schemes.isScheme(this._node.value)) {
                var references = schemes.getReferences(this._node.value, this.unit());
                references.forEach(function (reference) {
                    var includeNode = yaml.newScalar(reference);
                    includeNode.kind = yaml.Kind.INCLUDE_REF;
                    var includeAST = new ASTNode(includeNode, _this.unit(), null, null, null);
                    s.push(includeAST);
                });
            }
            return;
        }
        else if (kind == yaml.Kind.MAP) {
            var map = this._node;
            if (map.mappings.length == 1 && !inOneMemberMap) {
                new ASTNode(map.mappings[0].value, this._unit, this, inc, anc, this.cacheChildren).gatherIncludes(s);
            }
            else {
                map.mappings.
                    map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include, _this.cacheChildren); }).
                    forEach(function (x) { return x.gatherIncludes(s); });
            }
        }
        else if (kind == yaml.Kind.MAPPING) {
            var mapping = this._node;
            if (mapping.value == null) {
            }
            else {
                new ASTNode(mapping.value, this._unit, this, anc ? anc : this._anchor, inc ? inc : this._include, this.cacheChildren).gatherIncludes(s);
            }
        }
        else if (kind == yaml.Kind.SEQ) {
            var seq = this._node;
            seq.items.filter(function (x) { return x != null; }).map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include, _this.cacheChildren); }).forEach(function (x) { return x.gatherIncludes(s); });
        }
        else if (kind == yaml.Kind.INCLUDE_REF) {
            if (this._unit) {
                s.push(this);
            }
        }
    };
    ASTNode.prototype.setHighLevelParseResult = function (highLevelParseResult) {
        this._highLevelParseResult = highLevelParseResult;
    };
    ASTNode.prototype.highLevelParseResult = function () {
        return this._highLevelParseResult;
    };
    ASTNode.prototype.setHighLevelNode = function (highLevel) {
        this._highLevelNode = highLevel;
    };
    ASTNode.prototype.highLevelNode = function () {
        return this._highLevelNode;
    };
    ASTNode.prototype.start = function () {
        return this._node.startPosition;
    };
    ASTNode.prototype.errors = function () {
        return this._errors;
    };
    ASTNode.prototype.addIncludeError = function (error) {
        if (_.find(this._errors, function (currentError) { return currentError.message == error.message; }))
            return;
        var node = this._node;
        if (!node.includeErrors) {
            node.includeErrors = [];
        }
        if (_.find(node.includeErrors, function (currentError) { return currentError.message == error.message; }))
            return;
        this._errors.push(error);
        node.includeErrors.push(error);
    };
    ASTNode.prototype.parent = function () {
        return this._parent;
    };
    ASTNode.prototype.recalcEndPositionFromChilds = function () {
        var childs = this.children();
        //if(this.children().length == 0) return;
        var max = 0;
        var first = this.children()[0];
        var last = this.children()[this.children().length - 1];
        //this.children().forEach(n=> {
        //    var node: ASTNode = <ASTNode>n;
        //    if(node._node.endPosition > max) max = node._node.endPosition;
        //});
        if (this.isMapping()) {
            var mapping = this.asMapping();
            //console.log('reposition: mapping');
            if (mapping.value) {
                if (mapping.value.kind == yaml.Kind.MAP) {
                    var map = mapping.value;
                    if (map.startPosition < 0 && first) {
                        map.startPosition = first.start();
                    }
                    if (last)
                        this._node.endPosition = last._node.endPosition;
                    //console.log('embedded map: ' + map.startPosition + ".." + map.endPosition);
                    this._node.endPosition = Math.max(this._node.endPosition, mapping.value.endPosition);
                }
                else if (mapping.value.kind == yaml.Kind.SEQ) {
                    var seq = mapping.value;
                    if (seq.startPosition < 0) {
                        //console.log('*** missed start position');
                        if (seq.items.length > 0) {
                            var pos = seq.items[0].startPosition;
                            var range = new textutil.TextRange(this.unit().contents(), pos, pos);
                            range = range.extendSpacesBack().extendCharIfAnyBack('-');
                            seq.startPosition = range.startpos();
                        }
                        else {
                        }
                    }
                    //console.log('mapping1     : ' + mapping.startPosition + ".." + mapping.endPosition);
                    //console.log('embedded seq1: ' + seq.startPosition + ".." + seq.endPosition);
                    if (seq.items.length > 0) {
                        var ilast = seq.items[seq.items.length - 1];
                        this._node.endPosition = Math.max(this._node.endPosition, seq.endPosition, ilast.endPosition);
                        seq.endPosition = Math.max(this._node.endPosition, seq.endPosition, ilast.endPosition);
                    }
                    //console.log('embedded seq2: ' + seq.startPosition + ".." + seq.endPosition);
                    //console.log('mapping2     : ' + mapping.startPosition + ".." + mapping.endPosition);
                }
                else if (mapping.value.kind == yaml.Kind.SCALAR) {
                    //console.log('embedded scalar: ' + mapping.value.startPosition + ".." + mapping.value.endPosition);
                    //this._node.endPosition = mapping.value.endPosition;
                }
                else {
                    if (last)
                        this._node.endPosition = last._node.endPosition;
                }
            }
        }
        else {
            if (last)
                this._node.endPosition = last._node.endPosition;
        }
        //this._node.endPosition = max;;
    };
    ASTNode.prototype.isValueLocal = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            var knd = this._node.value.kind;
            return knd != yaml.Kind.INCLUDE_REF && knd != yaml.Kind.ANCHOR_REF;
        }
        return true;
    };
    ASTNode.prototype.keyStart = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            return this._node.key.startPosition;
        }
        return -1;
    };
    ASTNode.prototype.keyEnd = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            return this._node.key.endPosition;
        }
        return -1;
    };
    ASTNode.prototype.valueStart = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            var mapping = this.asMapping();
            if (mapping.value)
                return mapping.value.startPosition;
            else
                return mapping.endPosition;
        }
        else if (this._node.kind == yaml.Kind.SCALAR) {
            return this.start();
        }
        return -1;
    };
    ASTNode.prototype.valueEnd = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            var mapping = this.asMapping();
            return mapping.value ? mapping.value.endPosition : mapping.endPosition;
        }
        else if (this._node.kind == yaml.Kind.SCALAR) {
            return this.end();
        }
        return -1;
    };
    ASTNode.prototype.end = function () {
        return this._node.endPosition;
    };
    ASTNode.prototype.dump = function () {
        if (this._oldText) {
            return this._oldText;
        }
        if (this._unit && this._node.startPosition > 0 && this._node.endPosition > 0) {
            var originalText = this._unit.contents().substring(this._node.startPosition, this._node.endPosition);
            originalText = stripIndent(originalText, leadingIndent(this, this._unit.contents()));
            //console.log("L:");
            //console.log(originalText);
            return originalText;
        }
        return yaml.dump(this.dumpToObject(), {});
    };
    ASTNode.prototype.dumpToObject = function (full) {
        if (full === void 0) { full = false; }
        return this.dumpNode(this._node, full);
    };
    ASTNode.prototype.dumpNode = function (n, full) {
        var _this = this;
        if (full === void 0) { full = false; }
        if (!n) {
            return null;
        }
        if (n.kind == yaml.Kind.INCLUDE_REF) {
            if (this._unit) {
                var s = n;
                var includePath = s.value;
                var resolved = null;
                try {
                    resolved = this._unit.resolve(includePath);
                }
                catch (Error) {
                    //this will be reported during invalidation
                }
                if (resolved == null) {
                    return null;
                }
                else if (resolved.isRAMLUnit() && this.canInclude(resolved)) {
                    var currentUnit = this.unit();
                    var resolvedUnit = resolved;
                    resolvedUnit.addIncludedBy(currentUnit.absolutePath());
                    currentUnit.getIncludedByPaths().forEach(function (includedByPath) {
                        resolvedUnit.addIncludedBy(includedByPath);
                    });
                    var ast = resolved.ast();
                    if (ast) {
                        return ast.dumpToObject(full);
                    }
                }
                else if (this.canInclude(resolved)) {
                    return resolved.contents();
                }
            }
            return null;
        }
        if (n.kind == yaml.Kind.SEQ) {
            var seq = n;
            var arr = [];
            seq.items.forEach(function (x) { return arr.push(_this.dumpNode(x, full)); });
            return arr;
        }
        if (n.kind == yaml.Kind.ANCHOR_REF) {
            var aref = n;
            return this.dumpNode(aref.value, full);
        }
        if (n.kind == yaml.Kind.MAPPING) {
            var c = n;
            var v = {};
            var val = c.value;
            var mm = this.dumpNode(val, full);
            v["" + this.dumpNode(c.key, full)] = mm;
            return v;
        }
        if (n.kind == yaml.Kind.SCALAR) {
            var s = n;
            var q = s.value;
            if (s.plainScalar) {
                q = tryParseScalar(q);
            }
            return q;
        }
        if (n.kind == yaml.Kind.MAP) {
            var map = n;
            var res = {};
            if (map.mappings) {
                map.mappings.forEach(function (x) {
                    var ms = _this.dumpNode(x.value, full);
                    if (ms == null) {
                        ms = full ? "!$$$novalue" : ms;
                    }
                    //if (ms!=null||full) {
                    res[_this.dumpNode(x.key, full) + ""] = ms;
                    //}
                });
            }
            return res;
        }
    };
    ASTNode.prototype.keyKind = function () {
        if (this._node.key) {
            return this._node.key.kind;
        }
        return null;
    };
    ASTNode.prototype._actualNode = function () {
        return this._node;
    };
    ASTNode.prototype.execute = function (cmd) {
        if (this.unit()) {
            this.unit().project().execute(cmd);
        }
        else {
            cmd.commands.forEach(function (x) {
                switch (x.kind) {
                    case lowlevel.CommandKind.CHANGE_VALUE:
                        var attr = x.target;
                        var newValue = x.value;
                        var va = attr._actualNode();
                        var as = attr.start();
                        if (va.kind == yaml.Kind.MAPPING) {
                            va.value = yaml.newScalar("" + newValue);
                        }
                        //this.executeTextChange(new lowlevel.TextChangeCommand(as,attr.value().length,<string>newValue,attr.unit()))
                        return;
                    case lowlevel.CommandKind.CHANGE_KEY:
                        var attr = x.target;
                        var newValue = x.value;
                        var va = attr._actualNode();
                        if (va.kind == yaml.Kind.MAPPING) {
                            var sc = va.key;
                            sc.value = newValue;
                        }
                        return;
                }
            });
        }
    };
    ASTNode.prototype.updateFrom = function (n) {
        this._node = n;
    };
    ASTNode.prototype.isAnnotatedScalar = function () {
        if (!this.unit()) {
            return false;
        }
        var hlNode;
        var n = this;
        while (!hlNode && n) {
            hlNode = n.highLevelNode();
            n = n.parent();
        }
        if (hlNode) {
            var def = void 0;
            if (hlNode.isElement()) {
                def = hlNode.asElement().definition();
            }
            else {
                var p = hlNode.property();
                def = p && (p.domain() || p.range());
            }
            if (def) {
                var ver = def.universe().version();
                if (ver == "RAML08") {
                    return false;
                }
            }
        }
        var mappings;
        if (this.kind() == yaml.Kind.MAPPING && this.valueKind() == yaml.Kind.MAP) {
            mappings = this._node.value.mappings;
        }
        else if (this.key() == null && this.kind() == yaml.Kind.MAP) {
            mappings = this._node.mappings;
        }
        if (mappings) {
            var isScalar = mappings.length > 0;
            mappings.forEach(function (x) {
                if (x.key.value === "value") {
                    return;
                }
                if (x.key.value) {
                    if (x.key.value.charAt(0) == '(' && x.key.value.charAt(x.key.value.length - 1) == ')') {
                        return;
                    }
                }
                isScalar = false;
            });
            return isScalar;
        }
        return false;
    };
    //value caching proto
    // private valComputed = [false,false];
    //
    // private _val:any[] = [undefined,undefined];
    //
    //
    // value(toString?:boolean):any {
    //     //value caching proto
    //     if(toString){
    //         if(tru!this.valComputed[0]){
    //             this._val[0] = this._value(true);
    //             this.valComputed[0] = true;
    //         }
    //         return this._val[0];
    //     }
    //     else{
    //         if(!this.valComputed[1]){
    //             this._val[1] = this._value(false);
    //             this.valComputed[1] = true;
    //         }
    //         return this._val[1];
    //     }
    // }
    ASTNode.prototype.value = function (toString) {
        if (!this._node) {
            return "";
        }
        if (this._node.kind == yaml.Kind.SCALAR) {
            if (this._node['value'] === "~" && this._node['valueObject'] === null) {
                return null;
            }
            //TODO WHAT IS IT IS INCLUDE ACTUALLY
            if (!toString && ("" + this._node['valueObject'] === this._node['value'])) {
                return this._node['valueObject'];
            }
            var q = null;
            if (!this._node.hasOwnProperty("valueObject")) {
                q = this._node['value'];
            }
            else if (this._node['valueObject'] == null) {
                q = this._node['valueObject'];
            }
            else {
                q = this._node['value'];
            }
            if (!toString) {
                if (this._node.plainScalar) {
                    q = tryParseScalar(q);
                }
            }
            return q;
        }
        if (this._node.kind == yaml.Kind.ANCHOR_REF) {
            var ref = this._node;
            return new ASTNode(ref.value, this._unit, this, null, null).value(toString);
        }
        if (this._node.kind == yaml.Kind.MAPPING) {
            var map = this._node;
            if (map.value == null) {
                return null;
            }
            if (this.isAnnotatedScalar()) {
                var child = new ASTNode(map.value, this._unit, this, null, null);
                var ch = child.children();
                for (var i = 0; i < ch.length; i++) {
                    if (ch[i].key() === "value") {
                        if (ch[i].valueKind() == yaml.Kind.SEQ) {
                            return ch[i].children().map(function (x) { return x.value(); });
                        }
                        return ch[i].value();
                    }
                }
            }
            return new ASTNode(map.value, this._unit, this, null, null).value(toString);
        }
        if (this._node.kind == yaml.Kind.INCLUDE_REF) {
            //here we should resolve include
            var includeString = this._node['value'];
            var includePath = includeString;
            var resolved = null;
            try {
                resolved = this._unit.resolve(includePath);
            }
            catch (Error) {
                //not sure why we're returning this as a value, but that's what we do with failed units due to unknown cause below,
                //so doing the same @Denis
                return linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE_REASON, { path: includePath, reason: Error.message });
            }
            if (resolved == null) {
                return linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE, { path: includePath });
            }
            if (resolved.isRAMLUnit()) {
                var ast = resolved.ast();
                if (!ast) {
                    return linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE_REASON, { path: includePath, reason: "file is empty" });
                }
                return ast.value();
            }
            var text = resolved.contents();
            if (textutil.isMultiLineValue(text)) {
                text = textutil.fromMutiLine(text);
            }
            return text;
        }
        if (this._node.kind == yaml.Kind.MAP) {
            var amap = this._node;
            if (amap.mappings.length == 1) {
                //handle map with one member case differently
                return new ASTNode(amap.mappings[0], this._unit, this, null, null);
            }
            else if (this.isAnnotatedScalar()) {
                var ch = this.children();
                for (var i = 0; i < ch.length; i++) {
                    if (ch[i].key() === "value") {
                        if (ch[i].valueKind() == yaml.Kind.SEQ) {
                            return ch[i].children().map(function (x) { return x.value(); });
                        }
                        return ch[i].value();
                    }
                }
            }
        }
        if (this._node.kind == yaml.Kind.SEQ) {
            var aseq = this._node;
            if (aseq.items.length == 1 && true) {
                //handle seq with one member case differently
                return new ASTNode(aseq.items[0], this._unit, this, null, null).value(toString);
            }
        }
        //this are only kinds which has values
        return null;
    };
    ASTNode.prototype.printDetails = function (indent) {
        var result = "";
        if (!indent)
            indent = "";
        var typeName = this.kindName();
        if (this.kind() == yaml.Kind.SCALAR) {
            result += indent + "[" + typeName + "]" + " " + this.value() + "\n";
        }
        else if (this.kind() == yaml.Kind.MAPPING &&
            this._node.value &&
            this._node.value.kind == yaml.Kind.SCALAR) {
            result += indent + "[" + typeName + "]" + " " + this.key()
                + " = " + this.value() + "\n";
        }
        else if (this.kind() == yaml.Kind.MAPPING) {
            result += indent + "[" + typeName + "]" + " " + this.key()
                + " = :\n";
            this.children().forEach(function (child) {
                result += child.printDetails(indent + "\t");
            });
        }
        else {
            result += indent + "[" + typeName + "]" + " :\n";
            this.children().forEach(function (child) {
                result += child.printDetails(indent + "\t");
            });
        }
        return result;
    };
    ASTNode.prototype.visit = function (v) {
        this.children().forEach(function (x) {
            if (v(x)) {
                x.visit(v);
            }
        });
    };
    ASTNode.prototype.rawKey = function () {
        if (!this._node) {
            return "";
        }
        if (this._node.kind == yaml.Kind.MAPPING) {
            var map = this._node;
            if (map.key.kind == yaml.Kind.SEQ) {
                var items = map.key;
                var mn = "[";
                items.items.forEach(function (x) { return mn += x.value; });
                return mn + "]";
            }
            return map.key.value;
        }
        if (this._node.kind == yaml.Kind.INCLUDE_REF) {
            var m = this.children();
            if (m.length == 1) {
                return m[0].key();
            }
        }
        //other kinds do not have keys
        return null;
    };
    ASTNode.prototype.key = function (raw) {
        if (raw === void 0) { raw = false; }
        var key = this.rawKey();
        if (raw) {
            return key;
        }
        if (key != null && util.stringEndsWith(key, '?')) {
            key = key.substring(0, key.length - 1);
        }
        return key;
    };
    ASTNode.prototype.optional = function () {
        var key = this.rawKey();
        return key != null && util.stringEndsWith(key, '?');
    };
    ASTNode.prototype.addChild = function (n, pos) {
        if (pos === void 0) { pos = -1; }
        //this.show('ADD TARGET:');
        var node = n;
        //console.log('add-child: ' + this.kindName() + ' .add ' + node.kindName());
        node._parent = this;
        this._oldText = null;
        if (this.isMap()) {
            //console.log('pos: ' + pos);
            var map = this.asMap();
            if (map.mappings == null || map.mappings == undefined) {
                map.mappings = [];
            }
            if (pos >= 0) {
                map.mappings.splice(pos, 0, node.asMapping());
            }
            else {
                map.mappings.push(node.asMapping());
            }
        }
        else if (this.isMapping()) {
            var mapping = this.asMapping();
            var val = mapping.value;
            //console.log('mapping value: ' + val);
            if (!mapping.value && node.isMap()) {
                mapping.value = node._actualNode();
                return;
            }
            if (mapping.value && mapping.value.kind == yaml.Kind.SCALAR) {
                // cleanup old value
                mapping.value = null;
                val = null;
            }
            if (!val) {
                if (node.isScalar() || node.highLevelNode() && node.highLevelNode().property().getAdapter(services.RAMLPropertyParserService).isEmbedMap()) {
                    val = yaml.newSeq();
                }
                else {
                    val = yaml.newMap();
                }
                mapping.value = val;
            }
            if (val.kind == yaml.Kind.MAP) {
                var map = val;
                if (map.mappings == null || map.mappings == undefined) {
                    map.mappings = [];
                }
                if (node.isScalar()) {
                    // wrap it into ...
                    //node = cre
                }
                if (pos >= 0) {
                    map.mappings.splice(pos, 0, node.asMapping());
                }
                else {
                    map.mappings.push(node.asMapping());
                }
            }
            else if (val.kind == yaml.Kind.SEQ) {
                var seq = val;
                if (pos >= 0) {
                    seq.items.splice(pos, 0, node._actualNode());
                }
                else {
                    seq.items.push(node._actualNode());
                }
            }
            else {
                throw new Error(linter.applyTemplate(messageRegistry.INSERT_INTO_MAPPING_VALUE_NOT_SUPPORTED, { value: yaml.Kind[mapping.value.kind] }));
            }
        }
        else if (this.isSeq()) {
            var seq = this.asSeq();
            if (pos >= 0) {
                seq.items.splice(pos, 0, node._actualNode());
            }
            else {
                seq.items.push(node._actualNode());
            }
        }
        else {
            throw new Error(linter.applyTemplate(messageRegistry.INSERT_INTO_NOT_SUPPORTED, { name: this.kindName() }));
        }
    };
    ASTNode.prototype.removeChild = function (n) {
        this._oldText = null;
        var node = n;
        var ynode;
        var index;
        //console.log('*** REMOVE FROM: ' + this.kindName());
        if (this.kind() == yaml.Kind.SEQ) {
            //console.log('remove from seq');
            var seq = this.asSeq();
            //val = <yaml.YamlMap>((<yaml.YAMLMapping>this._node).value);
            ynode = node._node;
            index = seq.items.indexOf(ynode);
            if (index > -1)
                seq.items.splice(index, 1);
        }
        else if (this.kind() == yaml.Kind.MAP) {
            //val = <yaml.YamlMap>((<yaml.YAMLMapping>this._node).value);
            var map = this.asMap();
            //console.log('remove from map: ' + map.mappings.length);
            ynode = node.asMapping();
            index = map.mappings.indexOf(ynode);
            //console.log('  index: ' + index);
            if (index > -1)
                map.mappings.splice(index, 1);
            //console.log('  new len: ' + map.mappings.length);
        }
        else if (this.kind() == yaml.Kind.MAPPING) {
            //console.log('*** REMOVE FROM MAPPING');
            //val = <yaml.YamlMap>((<yaml.YAMLMapping>this._node).value);
            //console.log('remove from mapping with map as value');
            var mapping = this.asMapping();
            //this.show("REMOVE TARGET: ***");
            //node.show("REMOVE NODE: ***");
            if (node._actualNode() == mapping.value) {
                // remove right from mapping
                //console.log('*** remove map from mapping!');
                mapping.value = null;
            }
            else {
                var map = (mapping.value);
                ynode = node.asMapping();
                if (map && map.mappings) {
                    index = map.mappings.indexOf(ynode);
                    if (index > -1)
                        map.mappings.splice(index, 1);
                }
            }
        }
        else {
            throw new Error(linter.applyTemplate(messageRegistry.DELETE_FROM_NOT_SUPPORTED, { name: yaml.Kind[this.kind()] }));
        }
    };
    ASTNode.prototype.hasInnerIncludeError = function () {
        return this.innerIncludeErrors;
    };
    ASTNode.prototype.includeErrors = function () {
        if (this._node.kind == yaml.Kind.MAPPING) {
            var mapping = this._node;
            if (mapping.value == null) {
                return [];
            }
            var node = new ASTNode(mapping.value, this._unit, this, this._anchor, this._include);
            var res = node.includeErrors();
            this.innerIncludeErrors = node.hasInnerIncludeError();
            // if (res == null || res.length == 0) {
            //     <any>this._node
            // }
            return res;
        }
        var rs = [];
        if (this._node.kind == yaml.Kind.INCLUDE_REF) {
            var mapping = this._node;
            if (mapping.value == null) {
                return [];
            }
            var includePath = this.includePath();
            var resolved = null;
            try {
                resolved = this._unit.resolve(includePath);
            }
            catch (Error) {
                this.innerIncludeErrors = Error.inner;
                var s = linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE_REASON, { path: includePath, reason: Error.message });
                //known cause of failure
                rs.push(s);
                return rs;
            }
            var innerIncludeErrors = this._node.includeErrors;
            if (innerIncludeErrors && innerIncludeErrors.length > 0) {
                this.innerIncludeErrors = true;
                rs = innerIncludeErrors.map(function (innerError) {
                    if (typeof (innerError) == "object" && innerError instanceof Error) {
                        return innerError.message;
                    }
                    else {
                        return innerError.toString();
                    }
                });
                return rs;
            }
            if (resolved == null) {
                //unknown cause of failure
                rs.push(linter.applyTemplate(messageRegistry.CAN_NOT_RESOLVE, { path: includePath }));
                return rs;
            }
            if (resolved.isRAMLUnit()) {
                var ast = resolved.ast();
                if (ast) {
                    return [];
                }
                else {
                    rs.push(linter.applyTemplate(messageRegistry.CAN_NOT_BE_PARSED, { path: includePath }));
                }
            }
            else {
            }
        }
        return rs;
    };
    /**
     * Joins current mappings with mappings from "<<" anchor, if there is one.
     * @param mappings
     * @param inc
     * @param anc
     * @returns {any}
     */
    ASTNode.prototype.joinMappingsWithFullIncludeAnchor = function (mappings, inc, anc) {
        var _this = this;
        var fullAnchorMapping = _.find(mappings, function (mapping) {
            return mapping.key && mapping.value &&
                mapping.key.kind == yaml.Kind.SCALAR &&
                mapping.key.value == "<<" &&
                mapping.value.kind == yaml.Kind.ANCHOR_REF;
        });
        if (!fullAnchorMapping) {
            return mappings.map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include, _this.cacheChildren); });
        }
        var filteredMappings = _.filter(mappings, function (mapping) {
            return !(mapping.key.kind == yaml.Kind.SCALAR &&
                mapping.key.value == "<<" &&
                mapping.value.kind == yaml.Kind.ANCHOR_REF);
        });
        var childrenFromAnchor = new ASTNode(fullAnchorMapping.value, this._unit, this, inc, anc, this.cacheChildren).children(null, null, true);
        var filteredChildren = filteredMappings.map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include, _this.cacheChildren); });
        return filteredChildren.concat(childrenFromAnchor);
    };
    ASTNode.prototype.children = function (inc, anc, inOneMemberMap) {
        var _this = this;
        if (inc === void 0) { inc = null; }
        if (anc === void 0) { anc = null; }
        if (inOneMemberMap === void 0) { inOneMemberMap = true; }
        if (this._node == null) {
            return []; //TODO FIXME
        }
        if (this.cacheChildren && this._children) {
            return this._children;
        }
        var result;
        var kind = this._node.kind;
        if (kind == yaml.Kind.SCALAR) {
            result = [];
        }
        else if (kind == yaml.Kind.MAP) {
            var map = this._node;
            if (map.mappings.length == 1 && !inOneMemberMap) {
                //handle map with one member case differently
                // q:
                //  []
                //   - a
                //   - b
                // ->
                // q:
                //  a
                //  b
                result = new ASTNode(map.mappings[0].value, this._unit, this, inc, anc, this.cacheChildren).children(null, null, true);
            }
            else {
                //result = map.mappings.map(x=>new ASTNode(x, this._unit, this, anc ? anc : this._anchor, inc ? inc : this._include,this.cacheChildren));
                result = this.joinMappingsWithFullIncludeAnchor(map.mappings, inc, anc);
            }
        }
        else if (kind == yaml.Kind.MAPPING) {
            var mapping = this._node;
            if (mapping.value == null) {
                result = [];
            }
            else {
                var proxy = new ASTNode(mapping.value, this._unit, this, anc ? anc : this._anchor, inc ? inc : this._include, this.cacheChildren);
                result = proxy.children();
                if (proxy.includesContents()) {
                    this.setIncludesContents(true);
                }
            }
        }
        else if (kind == yaml.Kind.SEQ) {
            var seq = this._node;
            result = seq.items.filter(function (x) { return x != null; }).map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include, _this.cacheChildren); });
        }
        else if (kind == yaml.Kind.INCLUDE_REF) {
            if (this._unit) {
                var includePath = this.includePath();
                var resolved = null;
                try {
                    resolved = this._unit.resolve(includePath);
                }
                catch (Error) {
                    //this will be reported during invalidation
                }
                if (resolved == null) {
                    result = [];
                }
                else if (resolved.isRAMLUnit()) {
                    if (this.canInclude(resolved)) {
                        var currentUnit = this.unit();
                        var resolvedUnit = resolved;
                        resolvedUnit.addIncludedBy(currentUnit.absolutePath());
                        currentUnit.getIncludedByPaths().forEach(function (includedByPath) {
                            resolvedUnit.addIncludedBy(includedByPath);
                        });
                        var ast = resolved.ast();
                        if (ast) {
                            if (this.cacheChildren) {
                                ast = toChildCachingNode(ast);
                            } //else {
                            //    ast = <ASTNode>toIncludingNode(ast);
                            //}
                            result = resolved.ast().children(this, null);
                            this.setIncludesContents(true);
                        }
                    }
                    else {
                        if (this.addIncludeError) {
                            this.addIncludeError(new Error(messageRegistry.RECURSIVE_DEFINITION_EMPTY.message));
                        }
                    }
                }
            }
            if (!result) {
                result = [];
            }
        }
        else if (kind == yaml.Kind.ANCHOR_REF) {
            var ref = this._node;
            result = new ASTNode(ref.value, this._unit, this, null, null, this.cacheChildren).children();
        }
        else {
            throw new Error(linter.applyTemplate(messageRegistry.SHOULD_NEVER_HAPPEN_KIND, { kind: yaml.Kind[this._node.kind] }));
        }
        if (this.cacheChildren) {
            this._children = result;
        }
        return result;
    };
    ASTNode.prototype.canInclude = function (unit) {
        var includedFrom = this.includedFrom();
        while (includedFrom != null) {
            if (includedFrom.unit().absolutePath() == unit.absolutePath()) {
                return false;
            }
            includedFrom = includedFrom.includedFrom();
        }
        return !this.unit().includedByContains(unit.absolutePath());
    };
    ASTNode.prototype.directChildren = function (inc, anc, inOneMemberMap) {
        var _this = this;
        if (inc === void 0) { inc = null; }
        if (anc === void 0) { anc = null; }
        if (inOneMemberMap === void 0) { inOneMemberMap = true; }
        if (this._node) {
            switch (this._node.kind) {
                case yaml.Kind.SCALAR:
                    return [];
                case yaml.Kind.MAP:
                    {
                        var map = this._node;
                        if (map.mappings.length == 1 && !inOneMemberMap) {
                            //handle map with one member case differently
                            return new ASTNode(map.mappings[0].value, this._unit, this, inc, anc).directChildren(null, null, true);
                        }
                        return map.mappings.map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include); });
                    }
                case yaml.Kind.MAPPING:
                    {
                        var mapping = this._node;
                        if (mapping.value == null) {
                            return [];
                        }
                        return new ASTNode(mapping.value, this._unit, this, anc ? anc : this._anchor, inc ? inc : this._include).directChildren();
                    }
                case yaml.Kind.SEQ:
                    {
                        var seq = this._node;
                        return seq.items.filter(function (x) { return x != null; }).map(function (x) { return new ASTNode(x, _this._unit, _this, anc ? anc : _this._anchor, inc ? inc : _this._include); });
                    }
                case yaml.Kind.INCLUDE_REF:
                    {
                        return [];
                    }
                case yaml.Kind.ANCHOR_REF:
                    {
                        return [];
                    }
            }
            throw new Error(linter.applyTemplate(messageRegistry.SHOULD_NEVER_HAPPEN_KIND, { kind: yaml.Kind[this._node.kind] }));
        }
        return [];
    };
    ASTNode.prototype.anchorId = function () {
        return this._node.anchorId;
    };
    ASTNode.prototype.unit = function () {
        return this._unit;
        //if(this._unit) return this._unit;
        //if(!this.parent()) return null;
        //return this.parent().unit();
    };
    ASTNode.prototype.containingUnit = function () {
        if (this.valueKind() == yaml.Kind.INCLUDE_REF) {
            return this.unit().resolve(this._node.value.value);
        }
        if (this.kind() == yaml.Kind.INCLUDE_REF) {
            return this.unit().resolve(this._node.value);
        }
        return this._unit;
    };
    ASTNode.prototype.includeBaseUnit = function () {
        return this._unit;
    };
    ASTNode.prototype.setUnit = function (unit) {
        this._unit = unit;
    };
    ASTNode.prototype.includePath = function () {
        var includeString = this.getIncludeString();
        if (!includeString) {
            return null;
        }
        return includeString;
    };
    ASTNode.prototype.includeReference = function () {
        var includeString = this.getIncludeString();
        if (!includeString) {
            return null;
        }
        return refResolvers.getIncludeReference(includeString);
    };
    ASTNode.prototype.getIncludeString = function () {
        if (!this._node) {
            return null;
        }
        else if (this._node.kind == yaml.Kind.INCLUDE_REF) {
            var includePath = this._node['value'];
            return includePath;
        }
        else if (this._node.kind == yaml.Kind.MAPPING) {
            var mapping = this._node;
            if (mapping.value == null)
                return null;
            return new ASTNode(mapping.value, this._unit, this, null, null).getIncludeString();
        }
        else if (this._node.kind == yaml.Kind.ANCHOR_REF) {
            var ref = this._node.value;
            return new ASTNode(ref, this._unit, this, null, null).getIncludeString();
        }
        return null;
    };
    ASTNode.prototype.anchoredFrom = function () {
        return this._anchor;
    };
    ASTNode.prototype.includedFrom = function () {
        return this._include;
    };
    ASTNode.prototype.kind = function () {
        return this._actualNode().kind;
    };
    ASTNode.prototype.valueKind = function () {
        if (this._node.kind != yaml.Kind.MAPPING) {
            return null;
        }
        var map = this._node;
        if (!map.value) {
            return null;
        }
        return map.value.kind;
    };
    ASTNode.prototype.anchorValueKind = function () {
        if (this.valueKind() == yaml.Kind.ANCHOR_REF) {
            var ref = this._node.value;
            return ref && ref.value && ref.value.kind;
        }
        return null;
    };
    ASTNode.prototype.resolvedValueKind = function () {
        var vk = this.valueKind();
        if (vk == yaml.Kind.ANCHOR_REF) {
            var ak = this.anchorValueKind();
            if (ak == yaml.Kind.INCLUDE_REF) {
                var ref = this._node.value;
                var includePath = ref.value.value;
                return this.unitKind(includePath);
            }
            return ak;
        }
        else if (vk == yaml.Kind.INCLUDE_REF) {
            var includePath = this.includePath();
            return this.unitKind(includePath);
        }
        return vk;
    };
    ASTNode.prototype.unitKind = function (unitPath) {
        var resolved;
        try {
            resolved = this._unit.resolve(unitPath);
        }
        catch (Error) {
            return null;
        }
        if (resolved == null) {
            return yaml.Kind.SCALAR; //Error message is returned in this case
        }
        else if (resolved.isRAMLUnit()) {
            var ast = resolved.ast();
            if (ast) {
                return ast.kind();
            }
        }
        return yaml.Kind.SCALAR;
    };
    ASTNode.prototype.valueKindName = function () {
        var kind = this.valueKind();
        return kind != undefined ? yaml.Kind[kind] : null;
    };
    ASTNode.prototype.kindName = function () {
        return yaml.Kind[this.kind()];
    };
    ASTNode.prototype.indent = function (lev, str) {
        if (str === void 0) { str = ''; }
        var leading = '';
        //leading += '[' + lev + ']';
        for (var i = 0; i < lev; i++)
            leading += '  ';
        return leading + str;
    };
    ASTNode.prototype.replaceNewlines = function (s, rep) {
        if (rep === void 0) { rep = null; }
        var res = '';
        for (var i = 0; i < s.length; i++) {
            var ch = s[i];
            if (ch == '\r')
                ch = rep == null ? '\\r' : rep;
            if (ch == '\n')
                ch = rep == null ? '\\n' : rep;
            res += ch;
        }
        return res;
    };
    ASTNode.prototype.shortText = function (unittext, maxlen) {
        if (maxlen === void 0) { maxlen = 50; }
        var elen = this.end() - this.start();
        var len = elen;
        //var len = Math.min(elen,50);
        var unit = this.unit();
        if (!unittext && unit) {
            unittext = unit.contents();
        }
        var text;
        if (!unittext) {
            text = '[no-unit]';
        }
        else {
            var s = unittext;
            text = s ? s.substring(this.start(), this.end()) : '[no-text]';
        }
        text = "[" + this.start() + ".." + this.end() + "] " + elen + " // " + text + ' //';
        if (len < elen)
            text += '...';
        text = this.replaceNewlines(text);
        return text;
    };
    ASTNode.prototype.nodeShortText = function (node, unittext, maxlen) {
        if (maxlen === void 0) { maxlen = 50; }
        var elen = node.endPosition - node.startPosition;
        var len = elen;
        //var len = Math.min(elen,50);
        var unit = this.unit();
        if (!unittext && unit) {
            unittext = unit.contents();
        }
        var text;
        if (!unittext) {
            text = '[no-unit]';
        }
        else {
            var s = unittext;
            text = s ? s.substring(node.startPosition, node.endPosition) : '[no-text]';
        }
        text = "[" + node.startPosition + ".." + node.endPosition + "] " + elen + " // " + text + ' //';
        if (len < elen)
            text += '...';
        text = this.replaceNewlines(text);
        return text;
    };
    ASTNode.prototype.show = function (message, lev, text) {
        if (message === void 0) { message = null; }
        if (lev === void 0) { lev = 0; }
        if (text === void 0) { text = null; }
        if (message && lev == 0) {
            console.log(message);
        }
        var children = this.children();
        var desc = this.kindName();
        var val = this._actualNode().value;
        if (this.kind() == yaml.Kind.MAPPING) {
            desc += '[' + this._actualNode().key.value + ']';
        }
        if (val) {
            desc += "/" + yaml.Kind[val.kind];
        }
        else
            desc += "";
        if (children.length == 0) {
            //desc += "/" + this.value();
            console.log(this.indent(lev) + desc + " // " + this.shortText(text));
            if (this.isMapping() && this.asMapping().value) {
                console.log(this.indent(lev + 1) + '// ' + this.valueKindName() + ': ' + this.nodeShortText(this.asMapping().value, text));
            }
        }
        else {
            console.log(this.indent(lev) + desc + " { // " + this.shortText(text));
            if (this.isMapping() && this.asMapping().value) {
                console.log(this.indent(lev + 1) + '// ' + this.valueKindName() + ': ' + this.nodeShortText(this.asMapping().value, text));
            }
            children.forEach(function (node) {
                var n = node;
                n.show(null, lev + 1, text);
            });
            console.log(this.indent(lev) + '}');
        }
    };
    ASTNode.prototype.showParents = function (message, lev) {
        if (lev === void 0) { lev = 0; }
        if (message && lev == 0) {
            console.log(message);
        }
        var depth = 0;
        if (this.parent()) {
            var n = this.parent();
            depth = n.showParents(null, lev + 1);
        }
        var desc = this.kindName();
        var val = this._actualNode().value;
        if (val)
            desc += "/" + yaml.Kind[val.kind];
        else
            desc += "/null";
        console.log(this.indent(depth) + desc + " // " + this.shortText(null));
        return depth + 1;
    };
    ASTNode.prototype.inlined = function (kind) {
        return kind == yaml.Kind.SCALAR || kind == yaml.Kind.INCLUDE_REF;
    };
    ASTNode.prototype.markupNode = function (xbuf, node, lev, json) {
        if (json === void 0) { json = false; }
        var start = xbuf.text.length;
        //console.log('node: ' + node);
        switch (node.kind) {
            case yaml.Kind.MAP:
                if (json)
                    xbuf.append('{');
                var mappings = node.mappings;
                //console.log('map: ' + mappings.length);
                for (var i = 0; i < mappings.length; i++) {
                    if (json && i > 0)
                        xbuf.append(', ');
                    this.markupNode(xbuf, mappings[i], lev, json);
                }
                if (json)
                    xbuf.append('}');
                break;
            case yaml.Kind.SEQ:
                var items = node.items;
                //console.log('seq: ' + items.length);
                for (var i = 0; i < items.length; i++) {
                    xbuf.append(this.indent(lev, '- '));
                    //this.markupNode(xindent, pos+xbuf.text.length-(lev+1)*2, items[i], lev+1, xbuf);
                    this.markupNode(xbuf, items[i], lev + 1, json);
                }
                break;
            case yaml.Kind.MAPPING:
                var mapping = node;
                var val = mapping.value;
                //console.log('mapping: ' + mapping.key.value + ' ' + val.kind);
                if (json) {
                    if (!val) {
                        xbuf.append('\n');
                        break;
                    }
                    xbuf.append(mapping.key.value);
                    xbuf.append(': ');
                    if (val.kind == yaml.Kind.SCALAR) {
                        var sc = val;
                        xbuf.append(sc.value);
                    }
                    else if (val.kind == yaml.Kind.MAP) {
                        //var mp = <yaml.YamlMap>val;
                        this.markupNode(xbuf, mapping.value, lev + 1, json);
                    }
                    else {
                        throw new Error(linter.applyTemplate(messageRegistry.NOT_IMPLEMENTED_KIND, { kind: yaml.Kind[val.kind] }));
                    }
                    break;
                }
                xbuf.addWithIndent(lev, mapping.key.value + ':');
                if (!val) {
                    xbuf.append('\n');
                    break;
                }
                if (val.kind == yaml.Kind.SCALAR) {
                    var sc = val;
                    //if(!sc.value || sc.value.trim().length == 0) break;
                }
                //xbuf.append(this.indent(lev, mapping.key.value + ':'));
                if (mapping.value) {
                    xbuf.append(this.inlined(mapping.value.kind) ? ' ' : '\n');
                    this.markupNode(xbuf, mapping.value, lev + 1, json);
                }
                else {
                    xbuf.append('\n');
                }
                //console.log('xbuf: ' + xbuf);
                break;
            case yaml.Kind.SCALAR:
                var sc = node;
                if (textutil.isMultiLine(sc.value)) {
                    xbuf.append('|\n');
                    var lines = splitOnLines(sc.value);
                    for (var i = 0; i < lines.length; i++) {
                        xbuf.append(this.indent(lev, lines[i]));
                    }
                    xbuf.append('\n');
                }
                else {
                    xbuf.append(sc.value + '\n');
                }
                //console.log('SCALAR: ' + textutil.replaceNewlines(sc.value));
                break;
            case yaml.Kind.INCLUDE_REF:
                var ref = node;
                xbuf.append('!include ' + ref.value + '\n');
                break;
            default:
                throw new Error(linter.applyTemplate(messageRegistry.UNKNOWN_NODE_KIND, { kind: yaml.Kind[node.kind] }));
        }
        while (start < xbuf.text.length && xbuf.text[start] == ' ')
            start++;
        node.startPosition = start;
        node.endPosition = xbuf.text.length;
    };
    ASTNode.prototype.markup = function (json) {
        if (json === void 0) { json = false; }
        var buf = new MarkupIndentingBuffer('');
        this.markupNode(buf, this._actualNode(), 0, json);
        return buf.text;
    };
    ASTNode.prototype.root = function () {
        var node = this;
        while (node.parent()) {
            var p = node.parent();
            //if(p.isValueInclude()) break; // stop on include
            node = p;
        }
        return node;
    };
    ASTNode.prototype.parentOfKind = function (kind) {
        var p = this.parent();
        while (p) {
            if (p.kind() == kind)
                return p;
            p = p.parent();
        }
        return null;
    };
    ASTNode.prototype.find = function (name) {
        var found = null;
        //console.log('Looking for: ' + name);
        this.directChildren().forEach(function (y) {
            if (y.key() && y.key() == name) {
                if (!found)
                    found = y;
            }
        });
        return found;
    };
    ASTNode.prototype.shiftNodes = function (offset, shift, exclude) {
        this.directChildren().forEach(function (x) {
            if (exclude && exclude.start() == x.start() && exclude.end() == x.end()) {
                //console.log('exclude node: ' + x.start() + '..' + x.end());
                // exclude
            }
            else {
                var m = x.shiftNodes(offset, shift, exclude);
            }
        });
        if (exclude && exclude.start() == this.start() && exclude.end() == this.end()) {
            // exclude
            //console.log('exclude node: ' + this.start() + '..' + this.end());
        }
        else {
            var yaNode = this._actualNode();
            if (yaNode)
                innerShift(offset, yaNode, shift);
        }
        return null;
    };
    ASTNode.prototype.isMap = function () {
        return this.kind() == yaml.Kind.MAP;
    };
    ASTNode.prototype.isMapping = function () {
        return this.kind() == yaml.Kind.MAPPING;
    };
    ASTNode.prototype.isSeq = function () {
        return this.kind() == yaml.Kind.SEQ;
    };
    ASTNode.prototype.isScalar = function () {
        return this.kind() == yaml.Kind.SCALAR;
    };
    ASTNode.prototype.asMap = function () {
        if (!this.isMap())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "map", received: this.kindName() }));
        return (this._actualNode());
    };
    ASTNode.prototype.asMapping = function () {
        if (!this.isMapping())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping", received: this.kindName() }));
        return (this._actualNode());
    };
    ASTNode.prototype.asSeq = function () {
        if (!this.isSeq())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "seq", received: this.kindName() }));
        return (this._actualNode());
    };
    ASTNode.prototype.asScalar = function () {
        if (!this.isScalar())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "scalar", received: this.kindName() }));
        return (this._actualNode());
    };
    ASTNode.prototype.isValueSeq = function () {
        return this.valueKind() == yaml.Kind.SEQ;
    };
    ASTNode.prototype.isValueMap = function () {
        return this.valueKind() == yaml.Kind.MAP;
    };
    ASTNode.prototype.isValueInclude = function () {
        return this.valueKind() == yaml.Kind.INCLUDE_REF;
    };
    ASTNode.prototype.isValueScalar = function () {
        return this.valueKind() == yaml.Kind.SCALAR;
    };
    ASTNode.prototype.valueAsSeq = function () {
        if (!this.isMapping())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping", received: this.kindName() }));
        if (this.valueKind() != yaml.Kind.SEQ)
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping/seq", received: "mapping/" + this.kindName() }));
        return (this.asMapping().value);
    };
    ASTNode.prototype.valueAsMap = function () {
        if (!this.isMapping())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping", received: this.kindName() }));
        if (this.valueKind() != yaml.Kind.MAP)
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping/map", received: "mapping/" + this.kindName() }));
        return (this.asMapping().value);
    };
    ASTNode.prototype.valueAsScalar = function () {
        if (!this.isMapping())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping", received: this.kindName() }));
        if (this.valueKind() != yaml.Kind.SCALAR)
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping/scalar", received: "mapping/" + this.kindName() }));
        return (this.asMapping().value);
    };
    ASTNode.prototype.valueAsInclude = function () {
        if (!this.isMapping())
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping", received: this.kindName() }));
        if (this.valueKind() != yaml.Kind.INCLUDE_REF)
            throw new Error(linter.applyTemplate(messageRegistry.EXPECTED_INSTEAD_OF, { expected: "mapping/include", received: "mapping/" + this.kindName() }));
        return (this.asMapping().value);
    };
    ASTNode.prototype.text = function (unitText) {
        if (unitText === void 0) { unitText = null; }
        if (!unitText) {
            if (!this.unit())
                return '[no-text]';
            unitText = this.unit().contents();
        }
        return unitText.substring(this.start(), this.end());
    };
    ASTNode.prototype.copy = function () {
        var yn = copyNode(this._actualNode());
        return new ASTNode(yn, this._unit, this._parent, this._anchor, this._include, this._includesContents);
    };
    ASTNode.prototype.nodeDefinition = function () {
        return getDefinitionForLowLevelNode(this);
    };
    ASTNode.CLASS_IDENTIFIER = "jsyaml2lowLevel.ASTNode";
    return ASTNode;
}());
exports.ASTNode = ASTNode;
var InsertionPointType;
(function (InsertionPointType) {
    InsertionPointType[InsertionPointType["NONE"] = 0] = "NONE";
    InsertionPointType[InsertionPointType["START"] = 1] = "START";
    InsertionPointType[InsertionPointType["END"] = 2] = "END";
    InsertionPointType[InsertionPointType["POINT"] = 3] = "POINT";
})(InsertionPointType = exports.InsertionPointType || (exports.InsertionPointType = {}));
var InsertionPoint = /** @class */ (function () {
    function InsertionPoint(type, point) {
        if (point === void 0) { point = null; }
        this.type = type;
        this.point = point;
    }
    InsertionPoint.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), InsertionPoint.CLASS_IDENTIFIER);
    };
    InsertionPoint.prototype.getClassIdentifier = function () {
        var superIdentifiers = [];
        return superIdentifiers.concat(InsertionPoint.CLASS_IDENTIFIER);
    };
    InsertionPoint.after = function (point) {
        return new InsertionPoint(InsertionPointType.POINT, point);
    };
    InsertionPoint.atStart = function () {
        return new InsertionPoint(InsertionPointType.START);
    };
    InsertionPoint.atEnd = function () {
        return new InsertionPoint(InsertionPointType.END);
    };
    InsertionPoint.node = function () {
        return new InsertionPoint(InsertionPointType.NONE);
    };
    InsertionPoint.prototype.show = function (msg) {
        if (msg) {
            console.log(msg);
            console.log(linter.applyTemplate(messageRegistry.INSERTION_POINT_TYPE, { type: InsertionPointType[this.type] }));
        }
        else {
            console.log(linter.applyTemplate(messageRegistry.INSERTION_POINT_TYPE, { type: InsertionPointType[this.type] }));
        }
        if (this.type == InsertionPointType.POINT && this.point) {
            this.point.show();
        }
    };
    InsertionPoint.CLASS_IDENTIFIER = "jsyaml2lowLevel.InsertionPoint";
    return InsertionPoint;
}());
exports.InsertionPoint = InsertionPoint;
function createNode(key, parent, unit) {
    //console.log('create node: ' + key);
    var node = yaml.newMapping(yaml.newScalar(key), yaml.newMap());
    return new ASTNode(node, unit, parent, null, null);
}
exports.createNode = createNode;
function createMap(mappings) {
    //console.log('create node: ' + key);
    var node = yaml.newMap(mappings);
    return new ASTNode(node, null, null, null, null);
}
exports.createMap = createMap;
function createScalar(value) {
    var node = yaml.newScalar(value);
    return new ASTNode(node, null, null, null, null);
}
exports.createScalar = createScalar;
function createSeq(sn, parent, unit) {
    return new ASTNode(sn, unit, parent, null, null);
}
exports.createSeq = createSeq;
/*
export function createMappingWithMap(key:string, map: yaml.YAMLNode){
    //console.log('create node: ' + key);
    var node:yaml.YAMLNode=yaml.newMapping(yaml.newScalar(key),map);
    return new ASTNode(node,null,null,null,null);
}

export function createMap(){
    //console.log('create node: ' + key);
    var node:yaml.YAMLNode=yaml.newMap();
    return new ASTNode(node,null,null,null,null);
}
*/
function createSeqNode(key) {
    var node = yaml.newMapping(yaml.newScalar(key), yaml.newItems());
    return new ASTNode(node, null, null, null, null);
}
exports.createSeqNode = createSeqNode;
function createMapNode(key, unit) {
    if (unit === void 0) { unit = null; }
    var node = yaml.newMapping(yaml.newScalar(key), yaml.newMap());
    return new ASTNode(node, unit, null, null, null);
}
exports.createMapNode = createMapNode;
function createMapping(key, v) {
    //console.log('create mapping: ' + key);
    var node = yaml.newMapping(yaml.newScalar(key), yaml.newScalar(v));
    return new ASTNode(node, null, null, null, null);
}
exports.createMapping = createMapping;
function toChildCachingNode(node) {
    if (!(ASTNode.isInstance(node))) {
        return null;
    }
    var astNode = node;
    var result = new ASTNode(astNode.yamlNode(), astNode.unit(), null, null, null, true);
    result._errors = astNode._errors;
    return result;
}
exports.toChildCachingNode = toChildCachingNode;
function toIncludingNode(node) {
    if (!(ASTNode.isInstance(node))) {
        return null;
    }
    var astNode = node;
    var result = new ASTNode(astNode.yamlNode(), astNode.unit(), null, null, null, false);
    result._errors = astNode._errors;
    return result;
}
exports.toIncludingNode = toIncludingNode;
function getDefinitionForLowLevelNode(node) {
    var hl = node.highLevelNode();
    if (hl) {
        return hl.definition();
    }
    var parent = node.parent();
    if (!parent) {
        return null;
    }
    var key = node.key();
    if (!key) {
        return null;
    }
    var parentDef = parent.nodeDefinition();
    if (!parentDef) {
        return null;
    }
    if (!parentDef.property) {
        return null;
    }
    var prop = parentDef.property(key);
    if (!prop) {
        return null;
    }
    return prop.range();
}
exports.getDefinitionForLowLevelNode = getDefinitionForLowLevelNode;
function fetchMasterReference(unit, map, errors, lMap) {
    if (!unit.isOverlayOrExtension())
        return;
    var masterReferenceNode = unit.getMasterReferenceNode();
    if (!masterReferenceNode)
        return;
    var masterReferenceText = masterReferenceNode.value();
    if (!masterReferenceText)
        return;
    var unitPath = path.dirname(unit.absolutePath());
    var absIncludePath = lowlevel.toAbsolutePath(unitPath, masterReferenceText);
    if (map[absIncludePath]) {
        return;
    }
    if (errors[absIncludePath]) {
        masterReferenceNode.errors().push(new Error(errors[masterReferenceText]));
        return;
    }
    var arr = lMap[absIncludePath];
    if (!arr) {
        arr = [];
        lMap[absIncludePath] = arr;
    }
    arr.push(masterReferenceNode);
}
function fetchIncludesAndMasterAsync(project, apiPath) {
    var map = {};
    var errors = {};
    var nodes = [];
    var units = [];
    var processUnits = function (ind) {
        var refs = [];
        var lMap = {};
        while (ind < units.length) {
            var unit = units[ind];
            var unitPath = unit.absolutePath();
            fetchMasterReference(unit, map, errors, lMap);
            var includeNodes = unit.getIncludeNodes();
            includeNodes.forEach(function (x) {
                var ip = x.includePath();
                if (!ip)
                    return;
                var includeReference = refResolvers.getIncludeReference(ip);
                if (includeReference) {
                    refs.push(project.resolveAsync(unit.absolutePath(), ip));
                    return;
                }
                if (!ip)
                    return;
                var absIncludePath = lowlevel.buildPath(ip, unitPath, project.getRootPath());
                if (map[absIncludePath]) {
                    return;
                }
                if (errors[absIncludePath]) {
                    if (x.errors) {
                        x.errors().push(new Error(errors[ip]));
                        return;
                    }
                }
                var arr = lMap[absIncludePath];
                if (!arr) {
                    arr = [];
                    lMap[absIncludePath] = arr;
                }
                arr.push(x);
            });
            ind++;
        }
        var unitPaths = Object.keys(lMap);
        if (refs.length == 0 && unitPaths.length == 0) {
            return Promise.resolve();
        }
        var promises = refs;
        unitPaths.forEach(function (unitPath) {
            promises.push(project.unitAsync(unitPath, true).then(function (x) {
                if (!map[x.absolutePath()]) {
                    map[x.absolutePath()] = true;
                    units.push(x);
                }
            }, function (x) {
                var innerError = project.pathToUnit[unitPath];
                lMap[unitPath].forEach(function (node) {
                    if (!innerError) {
                        if (node.errors) {
                            node.errors().push(new Error(x));
                        }
                    }
                    else {
                        //TODO : for now I disabled inner errors missing reference reporting
                        //to make sync & async versions of parsing behave the same.
                        //Sync version of parsing does not traverse schema references unless
                        //there is a sample pointing to the schema.
                        //If we choose to report such errors for all schemas in sync mode too
                        //following should be uncommented
                        // if ((<any>node).addIncludeError) {
                        //     (<any>node).addIncludeError(new Error(x))
                        // }
                    }
                });
                errors[unitPath] = x;
                project.failedUnits[unitPath] = x;
                if (innerError) {
                    x.inner = true;
                }
            }));
        });
        return Promise.all(promises).then(function (x) {
            return processUnits(ind);
        });
    };
    return project.unitAsync(apiPath, path.isAbsolute(apiPath)).then(function (x) {
        units.push(x);
        map[x.absolutePath()] = true;
        return processUnits(0);
    }).then(function (x) {
        return units.length > 0 ? units[0] : null;
    });
}
exports.fetchIncludesAndMasterAsync = fetchIncludesAndMasterAsync;
//# sourceMappingURL=jsyaml2lowLevel.js.map