function WinBox(params, _title){

    if(!(this instanceof WinBox)) {

        return new WinBox(params);
    }

    body || setup();

    let id,
        index,
        root,
        tpl,
        title,
        icon,
        mount,
        html,
        url,

        width,
        height,
        minwidth,
        minheight,
        maxwidth,
        maxheight,
        autosize,
        overflow,

        x,
        y,

        top,
        left,
        bottom,
        right,

        min,
        max,
        hidden,
        modal,

        background,
        border,
        header,
        classname,

        oncreate,
        onclose,
        onfocus,
        onblur,
        onmove,
        onresize,
        onfullscreen,
        onmaximize,
        onminimize,
        onrestore,
        onhide,
        onshow,
        onload;

    if(params){

        if(_title){

            title = params;
            params = _title;
        }

        if(typeof params === "string"){

            title = params;
        }
        else{

            id = params["id"];
            index = params["index"];
            root = params["root"];
            tpl = params["template"];
            title = title || params["title"];
            icon = params["icon"];
            mount = params["mount"];
            html = params["html"];
            url = params["url"];

            width = params["width"];
            height = params["height"];
            minwidth = params["minwidth"];
            minheight = params["minheight"];
            maxwidth = params["maxwidth"];
            maxheight = params["maxheight"];
            autosize = params["autosize"];
            overflow = params["overflow"];

            min = params["min"];
            max = params["max"];
            hidden = params["hidden"];
            modal = params["modal"];

            x = params["x"] || (modal ? "center" : 0);
            y = params["y"] || (modal ? "center" : 0);

            top = params["top"];
            left = params["left"];
            bottom = params["bottom"];
            right = params["right"];

            background = params["background"];
            border = params["border"];
            header = params["header"];
            classname = params["class"];

            oncreate = params["oncreate"];
            onclose = params["onclose"];
            onfocus = params["onfocus"];
            onblur = params["onblur"];
            onmove = params["onmove"];
            onresize = params["onresize"];
            onfullscreen = params["onfullscreen"];
            onmaximize = params["onmaximize"];
            onminimize = params["onminimize"];
            onrestore = params["onrestore"];
            onhide = params["onhide"];
            onshow = params["onshow"];
            onload = params["onload"];
        }
    }

    this.dom = template(tpl);
    this.dom.id = this.id = id || ("winbox-" + (++id_counter));
    this.dom.className = "winbox" + (classname ? " " + (typeof classname === "string" ? classname : classname.join(" ")) : "") + (modal ? " modal" : "");
    this.dom["winbox"] = this;
    this.window = this.dom;
    this.body = getByClass(this.dom, "wb-body");
    this.header = header || 35;
    //this.plugins = [];

    stack_win.push(this);

    if(background){

        this.setBackground(background);
    }

    if(border){

        setStyle(this.body, "margin", border + (isNaN(border) ? "" : "px"));
    }
    else{

        border = 0;
    }

    if(header){

        const node = getByClass(this.dom, "wb-header");
        setStyle(node, "height", header + "px");
        setStyle(node, "line-height", header + "px");
        setStyle(this.body, "top", header + "px");
    }

    if(title){

        this.setTitle(title);
    }

    if(icon){

        this.setIcon(icon);
    }

    if(mount){

        this.mount(mount);
    }
    else if(html){

        this.body.innerHTML = html;
    }
    else if(url){

        this.setUrl(url, onload);
    }

    top = top ? parse(top, root_h) : 0;
    bottom = bottom ? parse(bottom, root_h) : 0;
    left = left ? parse(left, root_w) : 0;
    right = right ? parse(right, root_w) : 0;

    const viewport_w = root_w - left - right;
    const viewport_h = root_h - top - bottom;

    maxwidth = maxwidth ? parse(maxwidth, viewport_w) : viewport_w;
    maxheight = maxheight ? parse(maxheight, viewport_h) : viewport_h;
    minwidth = minwidth ? parse(minwidth, maxwidth) : 150;
    minheight = minheight ? parse(minheight, maxheight) : this.header;

    if(autosize){

        (root || body).appendChild(this.body);

        width = Math.max(Math.min(this.body.clientWidth + border * 2 + 1, maxwidth), minwidth);
        height = Math.max(Math.min(this.body.clientHeight + this.header + border + 1, maxheight), minheight);

        this.dom.appendChild(this.body);
    }
    else{

        width = width ? parse(width, maxwidth) : Math.max(maxwidth / 2, minwidth) | 0;
        height = height ? parse(height, maxheight) : Math.max(maxheight / 2, minheight) | 0;
    }

    x = x ? parse(x, viewport_w, width) : left;
    y = y ? parse(y, viewport_h, height) : top;

    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.minwidth = minwidth;
    this.minheight = minheight;
    this.maxwidth = maxwidth;
    this.maxheight = maxheight;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
    this.left = left;
    this.index = index;
    this.overflow = overflow;
    //this.border = border;
    this.min = false;
    this.max = false;
    this.full = false;
    this.hidden = false;
    this.focused = false;

    this.onclose = onclose;
    this.onfocus = onfocus;
    this.onblur = onblur;
    this.onmove = onmove;
    this.onresize = onresize;
    this.onfullscreen = onfullscreen;
    this.onmaximize = onmaximize;
    this.onminimize = onminimize;
    this.onrestore = onrestore;
    this.onhide = onhide;
    this.onshow = onshow;

    if(hidden){

        this.hide();
    }
    else{

        this.focus();
    }

    if(index || (index === 0)){

        this.index = index;
        setStyle(this.dom, "z-index", index);
        if(index > index_counter) index_counter = index;
    }

    if(max){

        this.maximize();
    }
    else if(min){

        this.minimize();
    }
    else{

        this.resize().move();
    }

    register(this);
    (root || body).appendChild(this.dom);
    oncreate && oncreate.call(this, params);
}
@param {string|Object=} params
@param {Object=} _title
@constructor
@this WinBox