/*
THIS INFRAGISTICS ULTIMATE SOFTWARE LICENSE  AGREEMENT ("AGREEMENT") LOCATED HERE:
https://www.infragistics.com/legal/license/igultimate-la
https://www.infragistics.com/legal/license/igultimate-eula
GOVERNS THE LICENSING, INSTALLATION AND USE OF INFRAGISTICS SOFTWARE. BY DOWNLOADING AND/OR INSTALLING AND USING INFRAGISTICS SOFTWARE:  you are indicating that you have read and understand this Agreement, and agree to be legally bound by it on behalf of the yourself and your company.
*/
import { Base, NotSupportedException, typeCast, Date_$type, markType } from "./type";
import { TypeDescriptionContext } from "./TypeDescriptionContext";
import { DescriptionTreeNode } from "./DescriptionTreeNode";
import { DescriptionSerializerBuilder } from "./DescriptionSerializerBuilder";
import { DescriptionTreeBuilder } from "./DescriptionTreeBuilder";
import { DescriptionResult } from "./DescriptionResult";
import { JsonDictionaryParser } from "./JsonDictionaryParser";
import { JsonDictionaryObject } from "./JsonDictionaryObject";
import { EmbeddedRefDescription } from "./EmbeddedRefDescription";
import { JsonDictionaryArray } from "./JsonDictionaryArray";
import { PointDescription } from "./PointDescription";
import { SizeDescription } from "./SizeDescription";
import { RectDescription } from "./RectDescription";
import { NotImplementedException } from "./NotImplementedException";
import { Convert } from "./Convert";
import { truncate } from "./number";
import { stringEndsWith, stringStartsWith, stringReplace } from "./string";
/**
 * @hidden
 */
export let DescriptionSerializer = /*@__PURE__*/ (() => {
    class DescriptionSerializer extends Base {
        constructor() {
            super();
            this.h = false;
            this.g = false;
            this.f = false;
            this.i = null;
            this.e = false;
        }
        p(a, b) {
            let c = DescriptionTreeBuilder.createTree(a, b);
            let d = new DescriptionSerializerBuilder();
            this.q(a, c, d);
            return d.toString();
        }
        t(a, b, c) {
            this.q(a, b, c);
        }
        c(a, b) {
            let c = new JsonDictionaryParser();
            let d = c.parse(b);
            return this.d(a, d, false, null, false);
        }
        d(a, b, c, d, e) {
            if (!(typeCast(JsonDictionaryObject.$, b) !== null)) {
                throw new NotSupportedException(1, "expected an object at the root of the json");
            }
            let f = b;
            if (c) {
                this.f = true;
                this.i = d;
            }
            if (e) {
                this.e = true;
            }
            let g = this.b(a, f);
            this.f = false;
            this.i = null;
            this.e = false;
            return g;
        }
        v(a, b, c, d, e) {
            if (this.g) {
                a.af(b, c, d, e);
            }
            else {
                a.ae(b, c, d, e);
            }
        }
        b(a, b, c = 8) {
            if (!b.g("type")) {
                if (b.g("refType")) {
                    let d = new EmbeddedRefDescription();
                    d.refType = b.item("refType").value;
                    d.value = b.item("id").value;
                    let e = new DescriptionResult();
                    e.result = d;
                    return e;
                }
                else {
                    throw new NotSupportedException(1, "expected type to be defined for the json object");
                }
            }
            let f = new DescriptionResult();
            let g = b.item("type").value;
            let h = a.v(g);
            f.result = h;
            if (h == null) {
                if (this.h) {
                    throw new NotSupportedException(1, "missing description for type: " + g);
                }
                f.d("couldn't find registered description for type: " + g);
                return f;
            }
            let i = b.e();
            for (let j = 0; j < i.length; j++) {
                let k = i[j];
                let l = a.getMetadata(g, TypeDescriptionContext.aa(k));
                if (l == null) {
                    if (TypeDescriptionContext.aa(k) == "Name") {
                        let m = "string";
                        let n = b.item(k);
                        let o = this.j(f, a, n, m);
                        h.name = o;
                    }
                    continue;
                }
                let p = b.item(k);
                if (l.knownType == 14 || l.knownType == 11 || l.knownType == 12) {
                    let q = p;
                    switch (l.knownType) {
                        case 14:
                            q = DescriptionSerializer.l(a, p);
                            break;
                        case 12:
                            q = DescriptionSerializer.m(a, p);
                            break;
                        case 11:
                            q = DescriptionSerializer.k(a, p);
                            break;
                    }
                    if (!this.e) {
                        this.v(a, h, k, l, q);
                    }
                }
                else if (typeCast(JsonDictionaryObject.$, p) !== null) {
                    let r = p;
                    let s = this.b(a, r, l.knownType);
                    f.e(s);
                    this.v(a, h, k, l, s.result);
                }
                else if (typeCast(JsonDictionaryArray.$, p) !== null) {
                    let t = p;
                    let u = "string";
                    let v = false;
                    if (l.knownType == 10) {
                        u = l.specificExternalType;
                    }
                    if (l.knownType == 9) {
                        v = true;
                        u = l.collectionElementType;
                    }
                    let w = this.a(f, a, t, u);
                    if (this.f) {
                        if (l.propertyName.toLowerCase() == "includedproperties" || l.propertyName.toLowerCase() == "excludedproperties") {
                            let x = w;
                            let y = new Array(x.length);
                            for (let z = 0; z < x.length; z++) {
                                y[z] = this.n(x[z]);
                            }
                            w = y;
                        }
                    }
                    if (!this.e || v) {
                        this.v(a, h, k, l, w);
                    }
                }
                else {
                    let aa = l.specificExternalType;
                    if (aa == null && l.knownType == 3) {
                        aa = "DateTime";
                    }
                    if (aa == null) {
                        aa = "String";
                    }
                    let ab = p;
                    let ac = this.j(f, a, ab, aa);
                    if (this.f) {
                        if (stringEndsWith(l.propertyName, "MemberPath") || stringEndsWith(l.propertyName.toLowerCase(), "field") || l.propertyName.toLowerCase() == "member" || l.propertyName.toLowerCase() == "membername" || (g != null && stringEndsWith(g, "Axis") && l.propertyName.toLowerCase() == "label")) {
                            ac = this.n(ac);
                        }
                    }
                    if (!this.e) {
                        this.v(a, h, k, l, ac);
                    }
                }
            }
            return f;
        }
        n(a) {
            let b = a.toString();
            if (this.i != null) {
                a = this.i(b);
            }
            else {
                if (stringStartsWith(b, "{")) {
                    if (!stringStartsWith(b, "{[")) {
                        b = b.substr(1, b.length - 2);
                        b = "{[" + b + "]}";
                        a = b;
                    }
                }
                else {
                    if (!stringStartsWith(b, "[")) {
                        b = "[" + b + "]";
                        a = b;
                    }
                }
            }
            return a;
        }
        static k(a, b) {
            if (b == null) {
                return null;
            }
            let c = NaN;
            let d = NaN;
            if (b.g("x")) {
                c = b.item("x").value;
            }
            if (b.g("y")) {
                d = b.item("y").value;
            }
            return ((() => {
                let $ret = new PointDescription();
                $ret.x = c;
                $ret.y = d;
                return $ret;
            })());
        }
        static m(a, b) {
            if (b == null) {
                return null;
            }
            let c = NaN;
            let d = NaN;
            if (b.g("width")) {
                c = b.item("width").value;
            }
            if (b.g("height")) {
                d = b.item("height").value;
            }
            return ((() => {
                let $ret = new SizeDescription();
                $ret.width = c;
                $ret.height = d;
                return $ret;
            })());
        }
        static l(a, b) {
            if (b == null) {
                return null;
            }
            let c = NaN;
            let d = NaN;
            let e = NaN;
            let f = NaN;
            if (b.g("left")) {
                c = b.item("left").value;
            }
            if (b.g("top")) {
                d = b.item("top").value;
            }
            if (b.g("width")) {
                e = b.item("width").value;
            }
            if (b.g("height")) {
                f = b.item("height").value;
            }
            return ((() => {
                let $ret = new RectDescription();
                $ret.left = c;
                $ret.top = d;
                $ret.width = e;
                $ret.height = f;
                return $ret;
            })());
        }
        a(a, b, c, d) {
            let e = new Array(c.items.length);
            for (let f = 0; f < c.items.length; f++) {
                let g = c.items[f];
                if (typeCast(JsonDictionaryObject.$, g) !== null) {
                    let h = g;
                    let i = this.b(b, h);
                    a.e(i);
                    e[f] = i.result;
                }
                else if (typeCast(JsonDictionaryArray.$, g) !== null) {
                    let j = g;
                    let k = this.a(a, b, j, d);
                    e[f] = k;
                }
                else {
                    let l = g;
                    let m = this.j(a, b, l, d);
                    e[f] = m;
                }
            }
            return e;
        }
        j(a, b, c, d) {
            switch (c.e) {
                case 1: return c.value;
                case 3: return c.value;
                case 0: switch (d.toLowerCase()) {
                    case "int": return truncate(c.value);
                    case "double": return c.value;
                    case "timespan": return c.value;
                    case "short": return truncate(c.value);
                    case "long": return truncate(c.value);
                    case "float": return c.value;
                    case "byte": return truncate(c.value);
                    default:
                        a.d("unexpected target type for number: " + d);
                        return c.value;
                }
                case 2:
                    if (d.toLowerCase() == "datetime") {
                        let val_ = c.value;
                        let e = (new Date(val_));
                        return e;
                    }
                    return c.value;
                default:
                    a.d("unexpected value type");
                    return c.value;
            }
        }
        q(a, b, c) {
            if (b == null) {
                c.e("null");
                return;
            }
            let d = false;
            c.f("{");
            c.i();
            c.e("\"type\": \"" + b.i + "\"");
            let e = b.f();
            for (let f = 0; f < e.count; f++) {
                let g = e._inner[f];
                if (g.c.toLowerCase() == "type") {
                    continue;
                }
                if (f >= 0) {
                    c.f(",");
                }
                this.r(a, b, g, c);
                d = true;
            }
            if (d) {
                c.f("");
            }
            c.h();
            c.f("}");
        }
        o(a) {
            if (a == null) {
                return null;
            }
            return a.substr(0, 1).toLowerCase() + a.substr(1);
        }
        r(a, b, c, d) {
            if (c.c.toLowerCase() == "type") {
                return;
            }
            d.e("\"" + this.o(c.c) + "\": ");
            this.u(a, b, c, c.b, d);
        }
        u(a, b, c, d, e) {
            let f = 2;
            if (c.a != null) {
                f = c.a.knownType;
            }
            switch (f) {
                case 6:
                case 16:
                case 23:
                case 10:
                    {
                        e.e("[");
                        let g = c.b;
                        let h = c.a.specificType;
                        if (c.a.knownType == 6 || c.a.knownType == 16) {
                            h = "String";
                        }
                        for (let i = 0; i < g.length; i++) {
                            if (i > 0) {
                                e.e(", ");
                            }
                            let j = h;
                            if (typeCast(DescriptionTreeNode.$, g[i]) !== null) {
                                this.q(a, g[i], e);
                            }
                            else {
                                this.s(a, h, g[i], e);
                            }
                        }
                        e.e("]");
                    }
                    break;
                case 7:
                    this.s(a, "Boolean", d, e);
                    break;
                case 9:
                    {
                        e.e("[");
                        let k = c.b;
                        let l = c.a.collectionElementType;
                        for (let m = 0; m < k.length; m++) {
                            if (m > 0) {
                                e.e(", ");
                            }
                            let n = l;
                            if (typeCast(DescriptionTreeNode.$, k[m]) !== null) {
                                this.q(a, k[m], e);
                            }
                            else {
                                this.s(a, l, k[m], e);
                            }
                        }
                        e.e("]");
                    }
                    break;
                case 4:
                case 18:
                case 19:
                case 20:
                case 22:
                case 5:
                case 2:
                    this.s(a, "String", d, e);
                    break;
                case 3:
                    this.s(a, "DateTime", d, e);
                    break;
                case 8:
                    if (c.a.specificExternalType.toLowerCase() == "string") {
                        this.s(a, "String", d, e);
                    }
                    else {
                        this.q(a, d, e);
                    }
                    break;
                case 1:
                    this.s(a, "Double", d, e);
                    break;
                case 14:
                case 12:
                case 11:
                    this.q(a, d, e);
                    break;
                case 21:
                    this.s(a, "TimeSpan", d, e);
                    break;
                case 17:
                    if (typeof d === 'string') {
                        this.s(a, "String", d, e);
                    }
                    else if (typeof d === 'number' || typeof d === 'number' || typeof d === 'number') {
                        this.s(a, "Number", d, e);
                    }
                    else if (typeCast(Date_$type, d) !== null) {
                        this.s(a, "DateTime", d, e);
                    }
                    else {
                        throw new NotImplementedException(0);
                    }
                    break;
                case 0:
                case 15:
                case 13: throw new NotImplementedException(0);
            }
        }
        s(a, b, c, d) {
            switch (b.toLowerCase()) {
                case "string":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e("\"" + stringReplace(c, "\"", "\\\"") + "\"");
                    }
                    break;
                case "number":
                case "double":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        if (!(typeof c === 'number')) {
                            c = Convert.toDouble3(c);
                        }
                        d.e(c.toString());
                    }
                    break;
                case "int":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e(c.toString());
                    }
                    break;
                case "float":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e(c.toString());
                    }
                    break;
                case "long":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e(c.toString());
                    }
                    break;
                case "decimal":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e(c.toString());
                    }
                    break;
                case "timespan":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        d.e(c.toString());
                    }
                    break;
                case "boolean":
                    d.e(c == null ? "false" : c.toString().toLowerCase());
                    break;
                case "datetime":
                    if (c == null) {
                        d.e("null");
                    }
                    else {
                        let v_ = c;
                        d.e("\"" + (v_.toJSON()) + "\"");
                    }
                    break;
            }
        }
    }
    DescriptionSerializer.$t = /*@__PURE__*/ markType(DescriptionSerializer, 'DescriptionSerializer');
    return DescriptionSerializer;
})();
