/*
*
* An XmlReader implementation for loading SGML (including HTML) converting it
* to well formed XML, by adding missing quotes, empty attribute values, ignoring
* duplicate attributes, case folding on tag names, adding missing closing tags
* based on SGML DTD information, and so on.
*
* Copyright (c) 2002 Microsoft Corporation. All rights reserved.
*
* Chris Lovett
*
*/
/* MD 2/27/13
 * This software is being re-used under the Microsoft Public License (MS-PL):
 * -----------------------------------------------------------------------------
 * This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the
 * license, do not use the software.
 *
 * 1. Definitions
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
 * A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes
 * its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 *
 * 2. Grant of Rights
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each
 *     contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare
 *     derivative works of its contribution, and distribute its contribution or any derivative works that you create.
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each
 *     contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use,
 *     sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution
 *     in the software.
 *
 * 3. Conditions and Limitations
 * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
 * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license
 *     from such contributor to the software ends automatically.
 * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are
 *     present in the software.
 * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete
 *     copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may
 *     only do so under a license that complies with this license.
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions.
 *     You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your
 *     local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
 * -----------------------------------------------------------------------------
 *
 * In addition, the public classes have been made internal and the namespace has been changed from Sgml to
 * Infragistics.Documents.Excel.Serialization.Excel2007.Sgml
 *
 * Also, I updated the code to work with Silverlight and WinRT.
 */
import { Base, fromEn, markType, BaseError, EnumUtil, fromEnum, NotSupportedException, String_$type } from "igniteui-angular-core";
import { AttDef } from "./AttDef";
import { AttList } from "./AttList";
import { stringFormat } from "igniteui-angular-core";
import { List$1 } from "igniteui-angular-core";
import { GroupType_$type } from "./GroupType";
import { Dictionary$2 } from "igniteui-angular-core";
import { Entity } from "./Entity";
import { StringBuilder } from "igniteui-angular-core";
import { NotImplementedException } from "igniteui-angular-core";
/**
 * @hidden
 */
export let ElementDecl = /*@__PURE__*/ (() => {
    class ElementDecl extends Base {
        constructor(a, b, c, d, e, f) {
            super();
            this.i = null;
            this.h = false;
            this.g = false;
            this.e = null;
            this.b = null;
            this.a = null;
            this.d = null;
            this.i = a;
            this.h = b;
            this.g = c;
            this.e = d;
            this.b = e;
            this.a = f;
        }
        c(a) {
            return this.d._item(a.toUpperCase());
        }
        j(a) {
            if (this.d == null) {
                this.d = a;
            }
            else {
                for (let b of fromEn(a)) {
                    if (this.d._item(b.f) == null) {
                        this.d._c(b);
                    }
                }
            }
        }
        f(a, b) {
            if (this.a != null) {
                let e = this.a;
                for (let d = 0; d < e.length; d++) {
                    let c = e[d];
                    if (c == a) {
                        return false;
                    }
                }
            }
            if (this.b != null) {
                let h = this.b;
                for (let g = 0; g < h.length; g++) {
                    let f = h[g];
                    if (f == a) {
                        return true;
                    }
                }
            }
            return this.e.c(a, b);
        }
    }
    ElementDecl.$t = markType(ElementDecl, 'ElementDecl');
    return ElementDecl;
})();
/**
 * @hidden
 */
export let ContentModel = /*@__PURE__*/ (() => {
    class ContentModel extends Base {
        constructor() {
            super();
            this.a = 0;
            this.d = 0;
            this.b = null;
            this.b = new Group(null);
        }
        i() {
            this.b = new Group(this.b);
            this.d++;
        }
        e() {
            if (this.d == 0) {
                return -1;
            }
            this.d--;
            this.b.a.i(this.b);
            this.b = this.b.a;
            return this.d;
        }
        h(a) {
            this.b.k(a);
        }
        f(a) {
            this.b.h(a);
        }
        g(a) {
            this.b.j(a);
        }
        j(a) {
            switch (a) {
                case "EMPTY":
                    this.a = 3;
                    break;
                case "RCDATA":
                    this.a = 2;
                    break;
                case "CDATA":
                    this.a = 1;
                    break;
                default: throw new BaseError(1, stringFormat("Declared content type '{0}' is not supported", a));
            }
        }
        c(a, b) {
            if (this.a != 0) {
                return false;
            }
            return this.b.d(a, b);
        }
    }
    ContentModel.$t = markType(ContentModel, 'ContentModel');
    return ContentModel;
})();
/**
 * @hidden
 */
export let Group = /*@__PURE__*/ (() => {
    class Group extends Base {
        constructor(a) {
            super();
            this.a = null;
            this.g = null;
            this.b = 0;
            this.c = 0;
            this.e = false;
            this.a = a;
            this.g = new List$1(Base.$, 0);
            this.b = 0;
            this.c = 0;
        }
        get f() {
            return this.e && this.g.count == 0;
        }
        i(a) {
            this.g.add1(a);
        }
        k(a) {
            if (a == "#PCDATA") {
                this.e = true;
            }
            else {
                this.g.add1(a);
            }
        }
        h(a) {
            if (!this.e && this.g.count == 0) {
                throw new BaseError(1, stringFormat("Missing token before connector '{0}'.", a));
            }
            let b = 0;
            switch (a) {
                case ',':
                    b = 3;
                    break;
                case '|':
                    b = 2;
                    break;
                case '&':
                    b = 1;
                    break;
            }
            if (this.b != 0 && this.b != b) {
                throw new BaseError(1, stringFormat("Connector '{0}' is inconsistent with {1} group.", a, EnumUtil.getName(GroupType_$type, this.b)));
            }
            this.b = b;
        }
        j(a) {
            let b = 0;
            switch (a) {
                case '?':
                    b = 1;
                    break;
                case '+':
                    b = 3;
                    break;
                case '*':
                    b = 2;
                    break;
            }
            this.c = b;
        }
        d(a, b) {
            for (let c of fromEnum(this.g)) {
                if (typeof c === 'string') {
                    if (c == a) {
                        return true;
                    }
                }
            }
            for (let d of fromEnum(this.g)) {
                if (typeof d === 'string') {
                    let e = d;
                    let f = b.d(e);
                    if (f != null) {
                        if (f.h) {
                            if (f.f(a, b)) {
                                return true;
                            }
                        }
                    }
                }
                else {
                    let g = d;
                    if (g.d(a, b)) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    Group.$t = markType(Group, 'Group');
    return Group;
})();
/**
 * @hidden
 */
export let SgmlDtd = /*@__PURE__*/ (() => {
    class SgmlDtd extends Base {
        constructor(a, b) {
            super();
            this.r = null;
            this.m = null;
            this.o = null;
            this.n = null;
            this.w = null;
            this.e = null;
            this.am = null;
            this.am = b;
            this.r = a;
            this.m = new Dictionary$2(String_$type, ElementDecl.$, 0);
            this.o = new Dictionary$2(String_$type, Entity.$, 0);
            this.n = new Dictionary$2(String_$type, Entity.$, 0);
            this.w = new StringBuilder(0);
        }
        get an() {
            return this.am;
        }
        static j(a, b, c, d, e, f, g) {
            let h = new SgmlDtd(b, g);
            if (d != null && d != "") {
                h.al(a, new Entity(0, h.r, c, d, f));
            }
            if (e != null && e != "") {
                h.al(a, new Entity(1, b, e));
            }
            try {
                h.x();
            }
            catch (i) {
                throw new BaseError(1, i.message + h.e.r());
            }
            return h;
        }
        static i(a, b, c, d, e, f, g) {
            let h = new SgmlDtd(b, g);
            h.al(a, new Entity(2, h.r, a, d, f));
            if (e != null && e != "") {
                h.al(a, new Entity(1, b, e));
            }
            try {
                h.x();
            }
            catch (i) {
                throw new BaseError(1, i.message + h.e.r());
            }
            return h;
        }
        f(a) {
            return this.n.item(a);
        }
        d(a) {
            return this.m.item(a.toUpperCase());
        }
        al(a, b) {
            b.ak(this.e, a);
            this.e = b;
            this.e.k();
        }
        ak() {
            if (this.e != null) {
                this.e.af();
            }
            if (this.e.b != null) {
                this.e = this.e.b;
            }
            else {
                this.e = null;
            }
        }
        x() {
            let a = this.e.j;
            while (true) {
                switch (a) {
                    case "\uffff":
                        this.ak();
                        if (this.e == null) {
                            return;
                        }
                        a = this.e.j;
                        break;
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        a = this.e.k();
                        break;
                    case '<':
                        this.ah();
                        a = this.e.k();
                        break;
                    case '%':
                        let b = this.h(SgmlDtd.v);
                        try {
                            this.al(this.e.ae, b);
                        }
                        catch (c) {
                        }
                        a = this.e.j;
                        break;
                    default:
                        this.e.ah("Unexpected character '{0}'", a);
                        break;
                }
            }
        }
        ah() {
            let a = this.e.k();
            if (a != '!') {
                this.e.ag("Found '{0}', but expecing declaration starting with '<!'");
                return;
            }
            a = this.e.k();
            if (a == '-') {
                a = this.e.k();
                if (a != '-') {
                    this.e.ah("Expecting comment '<!--' but found {0}", a);
                }
                this.e.y(this.w, "Comment", "-->");
            }
            else if (a == '[') {
                this.ag();
            }
            else {
                let b = this.e.z(this.w, SgmlDtd.v, true);
                switch (b) {
                    case "ENTITY":
                        this.ad();
                        break;
                    case "ELEMENT":
                        this.ac();
                        break;
                    case "ATTLIST":
                        this.z();
                        break;
                    default:
                        this.e.aj("Invalid declaration '<!{0}'.  Expecting 'ENTITY', 'ELEMENT' or 'ATTLIST'.", b);
                        break;
                }
            }
        }
        l() {
            let a = this.e.j;
            while (a == '-') {
                a = this.k(true);
            }
            return a;
        }
        k(a) {
            let b = this.e.n;
            let c = this.e.k();
            if (a && c != '-') {
                this.e.ah("Expecting comment delimiter '--' but found {0}", c);
            }
            this.e.y(this.w, "Markup Comment", "--");
            return this.e.l();
        }
        ag() {
            this.e.k();
            let a = this.u("[");
            if (a == "INCLUDE") {
                this.af();
            }
            else if (a == "IGNORE") {
                this.ae();
            }
            else {
                this.e.aj("Unsupported marked section type '{0}'", a);
            }
        }
        af() {
            throw new NotImplementedException(1, "Include Section");
        }
        ae() {
            let a = this.e.n;
            let b = this.e.l();
            if (b != '[') {
                this.e.ah("Expecting '[' but found {0}", b);
            }
            this.e.y(this.w, "Conditional Section", "]]>");
        }
        u(a) {
            let b = this.e.l();
            if (b == '%') {
                let c = this.h(a);
                b = this.e.j;
                if (!c.e) {
                    throw new NotSupportedException(1, "External parameter entity resolution");
                }
                return c.t.trim();
            }
            else {
                return this.e.z(this.w, a, true);
            }
        }
        h(a) {
            let b = this.e.k();
            let c = this.e.z(this.w, ";" + a, false);
            c = this.am.b(c);
            if (this.e.j == ';') {
                this.e.k();
            }
            let d = this.g(c);
            return d;
        }
        g(a) {
            let b = this.o.item(a);
            if (b == null) {
                this.e.aj("Reference to undefined parameter entity '{0}'", a);
            }
            return b;
        }
        ad() {
            let a = this.e.l();
            let b = (a == '%');
            if (b) {
                this.e.k();
                a = this.e.l();
            }
            let c = this.e.z(this.w, SgmlDtd.v, true);
            c = this.am.b(c);
            a = this.e.l();
            let d = null;
            if (a == '\"' || a == '\'') {
                let e = this.e.x(this.w, a);
                d = new Entity(1, c, e);
            }
            else {
                let f = null;
                let g = null;
                let h = this.e.z(this.w, SgmlDtd.v, true);
                if (Entity.f(h)) {
                    a = this.e.l();
                    let i = this.e.x(this.w, a);
                    d = new Entity(1, c, i);
                    d.al(h);
                }
                else {
                    g = h;
                    if (g == "PUBLIC") {
                        a = this.e.l();
                        if (a == '\"' || a == '\'') {
                            f = this.e.x(this.w, a);
                        }
                        else {
                            this.e.ah("Expecting public identifier literal but found '{0}'", a);
                        }
                    }
                    else if (g != "SYSTEM") {
                        this.e.aj("Invalid external identifier '{0}'.  Expecing 'PUBLIC' or 'SYSTEM'.", g);
                    }
                    let j = null;
                    a = this.e.l();
                    if (a == '\"' || a == '\'') {
                        j = this.e.x(this.w, a);
                    }
                    else if (a != '>') {
                        this.e.ah("Expecting system identifier literal but found '{0}'", a);
                    }
                    d = new Entity(0, c, f, j, this.e.v);
                }
            }
            a = this.e.l();
            if (a == '-') {
                a = this.l();
            }
            if (a != '>') {
                this.e.ah("Expecting end of entity declaration '>' but found '{0}'", a);
            }
            if (b) {
                this.o.addItem(d.u, d);
            }
            else {
                this.n.addItem(d.u, d);
            }
        }
        ac() {
            let a = this.e.l();
            let b = this.a(a, true);
            a = this.e.l().toUpperCase();
            let c = false;
            let d = false;
            if (a == 'O' || a == '-') {
                c = (a == 'O');
                this.e.k();
                a = this.e.l().toUpperCase();
                if (a == 'O' || a == '-') {
                    d = (a == 'O');
                    a = this.e.k();
                }
            }
            a = this.e.l();
            let e = this.c(a);
            a = this.e.l();
            let f = null;
            let g = null;
            if (a == '-') {
                a = this.e.k();
                if (a == '(') {
                    f = this.a(a, true);
                    a = this.e.l();
                }
                else if (a == '-') {
                    a = this.k(false);
                }
                else {
                    this.e.ah("Invalid syntax at '{0}'", a);
                }
            }
            if (a == '-') {
                a = this.l();
            }
            if (a == '+') {
                a = this.e.k();
                if (a != '(') {
                    this.e.ah("Expecting inclusions name group", a);
                }
                g = this.a(a, true);
                a = this.e.l();
            }
            if (a == '-') {
                a = this.l();
            }
            if (a != '>') {
                this.e.ah("Expecting end of ELEMENT declaration '>' but found '{0}'", a);
            }
            for (let i = 0; i < b.length; i++) {
                let h = b[i];
                let j = h.toUpperCase();
                j = this.am.b(h);
                this.m.addItem(j, new ElementDecl(j, c, d, e, g, f));
            }
        }
        a(a, b) {
            let c = new List$1(String_$type, 0);
            if (a == '(') {
                a = this.e.k();
                a = this.e.l();
                while (a != ')') {
                    a = this.e.l();
                    if (a == '%') {
                        let d = this.h(SgmlDtd.s);
                        this.al(this.e.ae, d);
                        this.aj(c, b);
                        this.ak();
                        a = this.e.j;
                    }
                    else {
                        let e = this.e.z(this.w, SgmlDtd.s, b);
                        e = e.toUpperCase();
                        let f = this.am.b(e);
                        c.add(f);
                    }
                    a = this.e.l();
                    if (a == '|' || a == ',') {
                        a = this.e.k();
                    }
                }
                this.e.k();
            }
            else {
                let g = this.e.z(this.w, SgmlDtd.v, b);
                g = g.toUpperCase();
                g = this.am.b(g);
                c.add(g);
            }
            return c.toArray();
        }
        aj(a, b) {
            let c = this.e.j;
            c = this.e.l();
            while (c != "\uffff") {
                let d;
                if (c == '%') {
                    let e = this.h(SgmlDtd.s);
                    this.al(this.e.ae, e);
                    this.aj(a, b);
                    this.ak();
                    c = this.e.j;
                }
                else {
                    d = this.e.z(this.w, SgmlDtd.s, true);
                    d = d.toUpperCase();
                    d = this.am.b(d);
                    a.add(d);
                }
                c = this.e.l();
                if (c == '|') {
                    c = this.e.k();
                    c = this.e.l();
                }
            }
        }
        c(a) {
            let b = new ContentModel();
            if (a == '(') {
                this.e.k();
                this.ai(')', b);
                a = this.e.k();
                if (a == '?' || a == '+' || a == '*') {
                    b.g(a);
                    this.e.k();
                }
            }
            else if (a == '%') {
                let c = this.h(SgmlDtd.q);
                this.al(this.e.ae, c);
                b = this.c(this.e.j);
                this.ak();
            }
            else {
                let d = this.u(SgmlDtd.q);
                b.j(d);
            }
            return b;
        }
        ai(a, b) {
            let c = b.d;
            let d = this.e.j;
            d = this.e.l();
            while (d != a || b.d > c) {
                if (d == "\uffff") {
                    this.e.ag("Content Model was not closed");
                }
                if (d == '%') {
                    let e = this.h(SgmlDtd.p);
                    this.al(this.e.ae, e);
                    this.ai("\uffff", b);
                    this.ak();
                    d = this.e.l();
                }
                else if (d == '(') {
                    b.i();
                    this.e.k();
                    d = this.e.l();
                }
                else if (d == ')') {
                    d = this.e.k();
                    if (d == '*' || d == '+' || d == '?') {
                        b.g(d);
                        d = this.e.k();
                    }
                    if (b.e() < c) {
                        this.e.ag("Parameter entity cannot close a paren outside it's own scope");
                    }
                    d = this.e.l();
                }
                else if (d == ',' || d == '|' || d == '&') {
                    b.f(d);
                    this.e.k();
                    d = this.e.l();
                }
                else {
                    let f;
                    if (d == '#') {
                        d = this.e.k();
                        f = "#" + this.e.z(this.w, SgmlDtd.p, true);
                    }
                    else {
                        f = this.e.z(this.w, SgmlDtd.p, true);
                    }
                    f = f.toUpperCase();
                    f = this.am.b(f);
                    d = this.e.j;
                    if (d == '?' || d == '+' || d == '*') {
                        b.i();
                        b.h(f);
                        b.g(d);
                        b.e();
                        this.e.k();
                        d = this.e.l();
                    }
                    else {
                        b.h(f);
                        d = this.e.l();
                    }
                }
            }
        }
        z() {
            let a = this.e.l();
            let b = this.a(a, true);
            let c = new AttList();
            this.aa(c, '>');
            for (let e = 0; e < b.length; e++) {
                let d = b[e];
                let f = this.m.item(d);
                if (f == null) {
                    this.e.aj("ATTLIST references undefined ELEMENT {0}", d);
                }
                f.j(c);
            }
        }
        aa(a, b) {
            let c = this.e.l();
            while (c != b) {
                if (c == '%') {
                    let d = this.h(SgmlDtd.t);
                    this.al(this.e.ae, d);
                    this.aa(a, "\uffff");
                    this.ak();
                    c = this.e.l();
                }
                else if (c == '-') {
                    c = this.l();
                }
                else {
                    let e = this.b(c);
                    a._c(e);
                }
                c = this.e.l();
            }
        }
        b(a) {
            a = this.e.l();
            let b = this.u(SgmlDtd.v);
            b = b.toUpperCase();
            b = this.am.b(b);
            let c = new AttDef(b);
            a = this.e.l();
            if (a == '-') {
                a = this.l();
            }
            this.ab(a, c);
            a = this.e.l();
            if (a == '-') {
                a = this.l();
            }
            this.y(a, c);
            a = this.e.l();
            if (a == '-') {
                a = this.l();
            }
            return c;
        }
        ab(a, b) {
            if (a == '%') {
                let c = this.h(SgmlDtd.v);
                this.al(this.e.ae, c);
                this.ab(this.e.j, b);
                this.ak();
                a = this.e.j;
                return;
            }
            if (a == '(') {
                b.a = this.a(a, false);
                b.c = 16;
            }
            else {
                let d = this.u(SgmlDtd.v);
                if (d == "NOTATION") {
                    a = this.e.l();
                    if (a != '(') {
                        this.e.ah("Expecting name group '(', but found '{0}'", a);
                    }
                    b.c = 15;
                    b.a = this.a(a, true);
                }
                else {
                    b.g(d);
                }
            }
        }
        y(a, b) {
            if (a == '%') {
                let c = this.h(SgmlDtd.v);
                this.al(this.e.ae, c);
                this.y(this.e.j, b);
                this.ak();
                a = this.e.j;
                return;
            }
            let d = true;
            if (a == '#') {
                this.e.k();
                let e = this.e.z(this.w, SgmlDtd.v, true);
                d = b.d(e);
                a = this.e.l();
            }
            if (d) {
                if (a == '\'' || a == '\"') {
                    let f = this.e.x(this.w, a);
                    b.e = f;
                    a = this.e.l();
                }
                else {
                    let g = this.e.z(this.w, SgmlDtd.v, false);
                    g = g.toUpperCase();
                    g = this.am.b(g);
                    b.e = g;
                    a = this.e.l();
                }
            }
        }
    }
    SgmlDtd.$t = markType(SgmlDtd, 'SgmlDtd');
    SgmlDtd.v = " \r\n\t";
    SgmlDtd.s = " \r\n\t|,)";
    SgmlDtd.q = " \r\n\t>";
    SgmlDtd.p = " \r\n\t,&|()?+*";
    SgmlDtd.t = " \t\r\n>";
    return SgmlDtd;
})();
