function t(t) {
    var e = {};
    t = t.split(",");
    for (var r = 0; r < t.length; r++) e[t[r]] = !0;
    return e;
}

function e(t) {
    return '"' + t + '"';
}

function r(t) {
    return t.replace(/<\?xml.*\?>\n/, "").replace(/<!doctype.*\>\n/, "").replace(/<!DOCTYPE.*\>\n/, "");
}

var a = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/, n = /^<\/([-A-Za-z0-9_]+)[^>]*>/, i = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g, s = t("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr"), o = t("a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video"), c = t("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var"), l = t("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr"), d = t("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected"), h = t("script,style"), u = function(t, e) {
    function r(t, r) {
        if (r) for (a = f.length - 1; 0 <= a && f[a] != r; a--) ; else var a = 0;
        if (0 <= a) {
            for (var n = f.length - 1; a <= n; n--) e.end && e.end(f[n]);
            f.length = a;
        }
    }
    var u, p, f = [], m = t;
    for (f.last = function() {
        return this[this.length - 1];
    }; t; ) {
        if (p = !0, f.last() && h[f.last()] ? (t = t.replace(new RegExp("([\\s\\S]*?)</" + f.last() + "[^>]*>"), function(t, r) {
            return r = r.replace(/\x3c!--([\s\S]*?)--\x3e|<!\[CDATA\[([\s\S]*?)]]\x3e/g, "$1$2"), 
            e.chars && e.chars(r), "";
        }), r(0, f.last())) : (0 == t.indexOf("\x3c!--") ? 0 <= (u = t.indexOf("--\x3e")) && (e.comment && e.comment(t.substring(4, u)), 
        t = t.substring(u + 3), p = !1) : 0 == t.indexOf("</") ? (u = t.match(n)) && (t = t.substring(u[0].length), 
        u[0].replace(n, r), p = !1) : 0 == t.indexOf("<") && (u = t.match(a)) && (t = t.substring(u[0].length), 
        u[0].replace(a, function(t, a, n, h) {
            if (a = a.toLowerCase(), o[a]) for (;f.last() && c[f.last()]; ) r(0, f.last());
            if (l[a] && f.last() == a && r(0, a), (h = s[a] || !!h) || f.push(a), e.start) {
                var u = [];
                n.replace(i, function(t, e, r, a, n) {
                    t = r || a || n || (d[e] ? e : ""), u.push({
                        name: e,
                        value: t,
                        escaped: t.replace(/(^|[^\\])"/g, '$1\\"')
                    });
                }), e.start && e.start(a, u, h);
            }
        }), p = !1), p && (p = (u = t.indexOf("<")) < 0 ? t : t.substring(0, u), t = u < 0 ? "" : t.substring(u), 
        e.chars && e.chars(p))), t == m) throw "Parse Error: " + t;
        m = t;
    }
    r();
}, p = {}, f = function() {};

p.html2json = function(t) {
    t = r(t);
    var e = [], a = {
        node: "root",
        child: []
    };
    return u(t, {
        start: function(t, r, n) {
            f(), t = {
                node: "element",
                tag: t
            }, 0 !== r.length && (t.attr = r.reduce(function(t, e) {
                var r = e.name, a = e.value;
                return a.match(/ /) && (a = a.split(" ")), t[r] ? Array.isArray(t[r]) ? t[r].push(a) : t[r] = [ t[r], a ] : t[r] = a, 
                t;
            }, {})), n ? (void 0 === (r = e[0] || a).child && (r.child = []), r.child.push(t)) : e.unshift(t);
        },
        end: function(t) {
            f();
            var r = e.shift();
            r.tag !== t && console.error("invalid state: mismatch end tag"), 0 === e.length ? a.child.push(r) : (void 0 === (t = e[0]).child && (t.child = []), 
            t.child.push(r));
        },
        chars: function(t) {
            if (f(), t = {
                node: "text",
                text: t
            }, 0 === e.length) a.child.push(t); else {
                var r = e[0];
                void 0 === r.child && (r.child = []), r.child.push(t);
            }
        },
        comment: function(t) {
            f(), t = {
                node: "comment",
                text: t
            };
            var r = e[0];
            void 0 === r.child && (r.child = []), r.child.push(t);
        }
    }), a;
}, p.json2html = function t(r) {
    var a = "area base basefont br col frame hr img input isindex link meta param embed".split(" "), n = "";
    r.child && (n = r.child.map(function(e) {
        return t(e);
    }).join(""));
    var i = "";
    return r.attr && "" !== (i = Object.keys(r.attr).map(function(t) {
        var a = r.attr[t];
        return Array.isArray(a) && (a = a.join(" ")), t + "=" + e(a);
    }).join(" ")) && (i = " " + i), "element" === r.node ? -1 < a.indexOf(r.tag) ? "<" + r.tag + i + "/>" : "<" + r.tag + i + ">" + n + "</" + r.tag + ">" : "text" === r.node ? r.text : "comment" === r.node ? "\x3c!--" + r.text + "--\x3e" : "root" === r.node ? n : void 0;
};

var m = function(t) {
    for (var e = [], r = [], a = 0, n = t.length; a < n; a++) if (0 == a) "view" != t[a].type && e.push(t[a]); else if ("view" == t[a].type) {
        if (0 < e.length) {
            var i = {
                type: "view",
                child: e
            };
            r.push(i);
        }
        e = [];
    } else "img" == t[a].type ? (0 < e.length && (i = {
        type: "view",
        child: e
    }, r.push(i)), e = t[a].attr, t[a].attr.width && -1 === t[a].attr.width.indexOf("%") && -1 === t[a].attr.width.indexOf("px") && (t[a].attr.width += "px"), 
    t[a].attr.height && -1 === t[a].attr.height.indexOf("%") && -1 === t[a].attr.height.indexOf("px") && (t[a].attr.height += "px"), 
    i = {
        type: "img",
        attr: e
    }, r.push(i), e = []) : (e.push(t[a]), a == n - 1 && (i = {
        type: "view",
        child: e
    }, r.push(i)));
    return r;
}, g = function(t) {
    var e = [];
    return function t(r) {
        var a = {};
        if ("root" != r.node) if ("element" == r.node) switch (r.tag) {
          case "a":
            a = {
                type: "a",
                text: r.child[0].text
            };
            break;

          case "img":
            a = {
                type: "img",
                text: r.text
            };
            break;

          case "p":
            a = {
                type: "view",
                text: r.text
            };
            break;

          case "div":
            a = {
                type: "view",
                text: r.text
            };
        } else "text" == r.node && (a = {
            type: "text",
            text: r.text
        });
        if (r.attr && (a.attr = r.attr), 0 != Object.keys(a).length && e.push(a), "a" != r.tag && (r = r.child)) for (var n in r) t(r[n]);
    }(t), e;
};

module.exports = {
    html2json: function(t) {
        return t = p.html2json(t), t = g(t), m(t);
    }
};