"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var rt = require("./typesystem");
var meta = require("./metainfo");
var restrictions_1 = require("./restrictions");
var restrictions_2 = require("./restrictions");
var exCalcFlag = "exampleCalculation";
function example(t) {
    var ms = t.oneMeta(meta.Example);
    if (ms) {
        return ms.example();
    }
    if (t.getExtra(exCalcFlag)) {
        return null;
    }
    t.putExtra(exCalcFlag, true);
    try {
        var ms1 = t.oneMeta(meta.Examples);
        if (ms1) {
            var examples = ms1.examples();
            if (examples && examples.length > 0) {
                return examples[0];
            }
        }
        var d = t.oneMeta(meta.Default);
        if (d) {
            return d.value();
        }
        if (t.isObject()) {
            var result = {};
            t.meta().forEach(function (x) {
                if (x instanceof restrictions_2.PropertyIs) {
                    var p = x;
                    var ex = example(p.value());
                    result[p.propertyName()] = ex;
                }
            });
            t.superTypes().forEach(function (x) {
                if (x.oneMeta(meta.Example) || x.oneMeta(meta.Examples)) {
                    var ex = example(x);
                    if (ex && typeof ex === "object") {
                        Object.keys(ex).forEach(function (key) {
                            result[key] = ex[key];
                        });
                    }
                }
            });
            return result;
        }
        if (t.isArray()) {
            var c = t.oneMeta(restrictions_1.ComponentShouldBeOfType);
            var resultArray = [];
            if (c) {
                resultArray.push(example(c.value()));
            }
            return resultArray;
        }
        if (t.isUnion()) {
            return example(t.typeFamily()[0]);
        }
        if (t.isNumber()) {
            return 1;
        }
        if (t.isBoolean()) {
            return true;
        }
        return "some value";
    }
    finally {
        t.putExtra(exCalcFlag, false);
    }
}
exports.example = example;
var Example = /** @class */ (function () {
    function Example(_value, _name, _displayName, _description, _strict, _annotations, _isSingle, _empty) {
        if (_name === void 0) { _name = undefined; }
        if (_displayName === void 0) { _displayName = undefined; }
        if (_description === void 0) { _description = undefined; }
        if (_strict === void 0) { _strict = true; }
        if (_isSingle === void 0) { _isSingle = false; }
        if (_empty === void 0) { _empty = false; }
        this._value = _value;
        this._name = _name;
        this._displayName = _displayName;
        this._description = _description;
        this._strict = _strict;
        this._annotations = _annotations;
        this._isSingle = _isSingle;
        this._empty = _empty;
        this.isExpanded = false;
        this._scalarsAnnotations = {};
        if (!this._annotations) {
            this._annotations = {};
        }
        else {
            this._hasAnnotations = true;
        }
        if (typeof this._strict != "boolean") {
            this._strict = false;
        }
    }
    Example.prototype.rawValue = function () { return this._value; };
    Example.prototype.isEmpty = function () {
        return this._empty;
    };
    Example.prototype.isJSONString = function () {
        if (this._isJSONString !== undefined) {
            return this._isJSONString;
        }
        this._isJSONString = false;
        var ch = this.firstCharacter();
        if (ch == "{" || ch == "[") {
            try {
                JSON.parse(this._value);
                this._isJSONString = true;
            }
            catch (e) { }
        }
        return this._isJSONString;
    };
    Example.prototype.isXMLString = function () {
        var ch = this.firstCharacter();
        return ch == "<";
    };
    Example.prototype.firstCharacter = function () {
        if (this._value == null) {
            return null;
        }
        if (typeof this._value !== "string") {
            return null;
        }
        var trim = this._value.trim();
        if (trim.length == 0) {
            return null;
        }
        return trim.charAt(0);
    };
    Example.prototype.asXMLString = function () {
        if (this.isXMLString()) {
            return this._value;
        }
        if (this._owner) {
            return this._owner.asXMLString();
        }
        return null;
    };
    Example.prototype.isYAML = function () {
        if (typeof this._value === "string") {
            return !(this.isJSONString() || this.isXMLString());
        }
        return true;
    };
    Example.prototype.asString = function () {
        if (typeof this._value === "string") {
            return "" + this._value;
        }
        return JSON.stringify(this._value, null, 2);
    };
    Example.prototype.asJSON = function () {
        if (this.isJSONString()) {
            try {
                return JSON.parse(this._value);
            }
            catch (e) {
                return null;
            }
        }
        if (this.isYAML()) {
            return this._value;
        }
        return this.asString();
    };
    Example.prototype.original = function () {
        return this._value;
    };
    Example.prototype.expandAsString = function () {
        return JSON.stringify(this.expandAsJSON(), null, 2);
    };
    Example.prototype.expandAsJSON = function () {
        if (!this.isEmpty()) {
            return this._value;
        }
        if (this.isExpanded) {
            return this._expandedValue;
        }
        this._expandedValue = example(this._ownerType);
        this.isExpanded = true;
        return this._expandedValue;
    };
    Example.prototype.isSingle = function () {
        return this._isSingle;
    };
    Example.prototype.strict = function () {
        return this._strict;
    };
    Example.prototype.description = function () {
        return this._description;
    };
    Example.prototype.displayName = function () {
        return this._displayName;
    };
    Example.prototype.annotations = function () {
        return this._annotations;
    };
    Example.prototype.name = function () {
        return this._name;
    };
    Example.prototype.scalarsAnnotations = function () {
        return this._scalarsAnnotations;
    };
    Example.prototype.registerScalarAnnotatoion = function (a, pName) {
        this._hasScalarAnnotations = true;
        var aMap = this._scalarsAnnotations[pName];
        if (!aMap) {
            aMap = {};
            this._scalarsAnnotations[pName] = aMap;
        }
        aMap[a.facetName()] = a;
    };
    Example.prototype.setOwner = function (owner) {
        this._owner = owner;
    };
    Example.prototype.owner = function () {
        return this._owner;
    };
    Example.prototype.setOwnerType = function (ownerType) {
        this._ownerType = ownerType;
    };
    Example.prototype.ownerType = function () {
        return this._ownerType;
    };
    Example.prototype.hasAnnotations = function () { return this._hasAnnotations; };
    Example.prototype.hasScalarAnnotations = function () { return this._hasScalarAnnotations; };
    return Example;
}());
var TSExample = /** @class */ (function () {
    function TSExample(_value, _name, _displayName, _description, _strict, _annotations, _isSingle, _empty) {
        if (_name === void 0) { _name = undefined; }
        if (_displayName === void 0) { _displayName = undefined; }
        if (_description === void 0) { _description = undefined; }
        if (_strict === void 0) { _strict = true; }
        if (_isSingle === void 0) { _isSingle = false; }
        if (_empty === void 0) { _empty = false; }
        this._value = _value;
        this._name = _name;
        this._displayName = _displayName;
        this._description = _description;
        this._strict = _strict;
        this._annotations = _annotations;
        this._isSingle = _isSingle;
        this._empty = _empty;
        this.isExpanded = false;
        this._scalarsAnnotations = {};
        if (!this._annotations) {
            this._annotations = {};
        }
        else {
            this._hasAnnotations = true;
        }
    }
    TSExample.prototype.annotationsMap = function () {
        var res = {};
        var sc = this.scalarsAnnotations();
        Object.keys(sc).forEach(function (x) {
            var l = [];
            Object.keys(sc[x]).forEach(function (y) {
                l.push(sc[x][y]);
            });
            res[x] = l;
        });
        return res;
    };
    TSExample.prototype.isEmpty = function () {
        return this._empty;
    };
    TSExample.prototype.isJSONString = function () {
        var ch = this.firstCharacter();
        return ch == "{" || ch == "[";
    };
    TSExample.prototype.isXMLString = function () {
        var ch = this.firstCharacter();
        return ch == "<";
    };
    TSExample.prototype.firstCharacter = function () {
        if (this._value == null) {
            return null;
        }
        if (typeof this._value !== "string") {
            return null;
        }
        var trim = this._value.trim();
        if (trim.length == 0) {
            return null;
        }
        return trim.charAt(0);
    };
    TSExample.prototype.asXMLString = function () {
        if (this.isXMLString()) {
            return this._value;
        }
        if (this._owner) {
            return this._owner.asXMLString();
        }
        return null;
    };
    TSExample.prototype.isYAML = function () {
        if (typeof this._value === "string") {
            return !(this.isJSONString() || this.isXMLString());
        }
        return true;
    };
    TSExample.prototype.asString = function () {
        if (typeof this._value === "string") {
            return "" + this._value;
        }
        return JSON.stringify(this._value, null, 2);
    };
    TSExample.prototype.asJSON = function () {
        if (this.isJSONString()) {
            try {
                return JSON.parse(this._value);
            }
            catch (e) {
                return null;
            }
        }
        if (this.isYAML()) {
            return this._value;
        }
        return this.asString();
    };
    TSExample.prototype.original = function () {
        return this._value;
    };
    TSExample.prototype.expandAsString = function () {
        return JSON.stringify(this.expandAsJSON(), null, 2);
    };
    TSExample.prototype.expandAsJSON = function () {
        if (!this.isEmpty()) {
            return this._value;
        }
        if (this.isExpanded) {
            return this._expandedValue;
        }
        this._expandedValue = example(this._ownerType);
        this.isExpanded = true;
        return this._expandedValue;
    };
    TSExample.prototype.value = function () {
        return this.expandAsJSON();
    };
    TSExample.prototype.isSingle = function () {
        return this._isSingle;
    };
    TSExample.prototype.strict = function () {
        return this._strict;
    };
    TSExample.prototype.description = function () {
        return this._description;
    };
    TSExample.prototype.displayName = function () {
        return this._displayName;
    };
    TSExample.prototype.annotations = function () {
        var _this = this;
        var res = [];
        Object.keys(this._annotations).forEach(function (x) {
            res.push(_this._annotations[x]);
        });
        return res;
    };
    TSExample.prototype.name = function () {
        return this._name;
    };
    TSExample.prototype.scalarsAnnotations = function () {
        return this._scalarsAnnotations;
    };
    TSExample.prototype.registerScalarAnnotatoion = function (a, pName) {
        this._hasScalarAnnotations = true;
        var aMap = this._scalarsAnnotations[pName];
        if (!aMap) {
            aMap = {};
            this._scalarsAnnotations[pName] = aMap;
        }
        aMap[a.facetName()] = a;
    };
    TSExample.prototype.setOwner = function (owner) {
        this._owner = owner;
    };
    TSExample.prototype.owner = function () {
        return this._owner;
    };
    TSExample.prototype.setOwnerType = function (ownerType) {
        this._ownerType = ownerType;
    };
    TSExample.prototype.ownerType = function () {
        return this._ownerType;
    };
    TSExample.prototype.hasAnnotations = function () { return this._hasAnnotations; };
    TSExample.prototype.hasScalarAnnotations = function () { return this._hasScalarAnnotations; };
    return TSExample;
}());
var toExample = function (owner, exampleObj, name, isSingle) {
    if (name === void 0) { name = null; }
    if (isSingle === void 0) { isSingle = false; }
    var example;
    if (exampleObj != null) {
        if (!exampleObj.hasOwnProperty("value")) {
            example = new Example(exampleObj, name, undefined, undefined, true, undefined, isSingle);
        }
        else {
            var val = exampleObj.value;
            var displayName = scalarValue(exampleObj, "displayName");
            var description = scalarValue(exampleObj, "description");
            var strict = scalarValue(exampleObj, "strict");
            var aObj_1 = {};
            scalarAnnotaitons(exampleObj).forEach(function (x) {
                aObj_1[x.facetName()] = x;
            });
            example = new Example(val, name, displayName, description, strict, aObj_1, isSingle);
            for (var _i = 0, _a = scalarAnnotaitons(exampleObj["displayName"]); _i < _a.length; _i++) {
                var a = _a[_i];
                example.registerScalarAnnotatoion(a, "displayName");
            }
            for (var _b = 0, _c = scalarAnnotaitons(exampleObj["description"]); _b < _c.length; _b++) {
                var a = _c[_b];
                example.registerScalarAnnotatoion(a, "description");
            }
            for (var _d = 0, _e = scalarAnnotaitons(exampleObj["strict"]); _d < _e.length; _d++) {
                var a = _e[_d];
                example.registerScalarAnnotatoion(a, "strict");
            }
        }
    }
    else {
        example = new Example(null, name, null, null, true, {}, isSingle);
    }
    if (example) {
        example.setOwner(owner);
    }
    return example;
};
function scalarValue(obj, propName) {
    var pVal = obj[propName];
    if (pVal != null && typeof (pVal) == "object") {
        return pVal["value"];
    }
    return pVal;
}
function scalarAnnotaitons(obj) {
    var result = [];
    if (!obj || typeof (obj) != "object") {
        return result;
    }
    for (var _i = 0, _a = Object.keys(obj).filter(function (x) { return x.length > 0 && x.charAt(0) == "(" && x.charAt(x.length - 1) == ")"; }); _i < _a.length; _i++) {
        var aKey = _a[_i];
        var aName = aKey.substring(1, aKey.length - 1);
        var aVal = obj[aKey];
        var a = new meta.Annotation(aName, aVal, aKey);
        result.push(a);
    }
    return result;
}
function exampleFromInheritedType(inheritedType) {
    var result = [];
    var ms1 = inheritedType.oneMeta(meta.Examples);
    if (ms1) {
        var vl = ms1.value();
        if (vl && typeof vl === "object") {
            var xmlValues;
            Object.keys(vl).forEach(function (key) {
                var name = Array.isArray(vl) ? null : key;
                var exampleObj = vl[key];
                var example = toExample({ asXMLString: function () {
                        if (!xmlValues) {
                            xmlValues = ms1.asXMLStrings();
                        }
                        return xmlValues[key];
                    },
                    ownerType: function () { return inheritedType; } }, exampleObj, name);
                result.push(example);
            });
        }
    }
    var ms = inheritedType.oneMeta(meta.Example);
    if (ms) {
        var exampleV = ms.example();
        if (exampleV != null) {
            result.push(toExample(ms, ms.value(), undefined, true));
        }
    }
    return result;
}
function exampleFromInheritedType2(inheritedType) {
    var arr = exampleFromInheritedType(inheritedType);
    var result = [];
    for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
        var e1 = arr_1[_i];
        var e = e1;
        var te = new TSExample(e.rawValue(), e.name(), e.displayName(), e.description(), e.strict(), e.annotations(), e.isSingle(), e.isEmpty());
        if (e.scalarsAnnotations()) {
            for (var _a = 0, _b = Object.keys(e.scalarsAnnotations()); _a < _b.length; _a++) {
                var pName = _b[_a];
                var pAnnotations = e.scalarsAnnotations()[pName];
                for (var _c = 0, _d = Object.keys(pAnnotations); _c < _d.length; _c++) {
                    var aName = _d[_c];
                    te.registerScalarAnnotatoion(pAnnotations[aName], pName);
                }
            }
        }
        result.push(te);
    }
    return result;
}
exports.exampleFromInheritedType2 = exampleFromInheritedType2;
function exampleFromNominal(nominalType, collectFromSupertype) {
    var originalInherited = nominalType.getAdapter(rt.InheritedType);
    if (originalInherited) {
        var originalTypeExamples = exampleFromInheritedType(originalInherited);
        if (originalTypeExamples && originalTypeExamples.length > 0) {
            return originalTypeExamples;
        }
        if (collectFromSupertype && nominalType.isUserDefined() && !nominalType.isGenuineUserDefinedType()
            && nominalType.genuineUserDefinedTypeInHierarchy()) {
            var genuineNominal = nominalType.genuineUserDefinedTypeInHierarchy();
            var genuineInherited = genuineNominal.getAdapter(rt.InheritedType);
            if (genuineInherited) {
                var genuineTypeExamples = exampleFromInheritedType(genuineInherited);
                if (genuineTypeExamples && genuineTypeExamples.length > 0) {
                    return genuineTypeExamples;
                }
            }
        }
    }
    if (originalInherited) {
        var ex = new Example(null, undefined, undefined, undefined, false, undefined, undefined, true);
        ex.setOwnerType(originalInherited);
        return [ex];
    }
    return [];
}
exports.exampleFromNominal = exampleFromNominal;
//# sourceMappingURL=exampleBuilder.js.map