cfgWidget = {
    hasIcon: true,
    hasSizeBtn: true,
    hasCloseBtn: true,
    hasRefreshBtn: true,
    hasSettingsBtn: true,
    hasDrag: true,
    hasOnCloseConfirm: false,
    hasProfile: false,
    isOpenHidden: false,
    isSystem: false,
    isWindow: true,
    title: "Jaws widget",
    module: "base",
    saveMethod: "GET",
    minSize: { width: 160, height: 120 }
}

SYSWIDGET_WKEY = 10000;

var mozilla_nav = (document.all) ? 0 : 1;
domTitleSettings = [
    { tag: "div", innerHTML: "Title:", className: "settings_section",
      childs: [
          {tag: "input", id: "input_title", type: "text", size: "25"},
          {tag: "input", type: "button", value: " Set ", events: {onclick: "settingsSetTitle()"}}
      ]},

    { tag: "div", className: "settings_section", style: {align: "left"},
      childs: {
        tag: "table", className: "sys_table",
        childs: {
          tag: "tr",
          childs: [
            {tag: "td", innerHTML: "Caption color:<br>"},
            {tag: "td", style: {width:22, height:22, background: "#FFFFCC"}, events: {onclick: "settingsSetCaption('#FFFFCC')"}},
            {tag: "td", style: {width:22, height:22, background: "#FFCCFF"}, events: {onclick: "settingsSetCaption('#FFCCFF')"}},
            {tag: "td", style: {width:22, height:22, background: "#CCFFFF"}, events: {onclick: "settingsSetCaption('#CCFFFF')"}},
            {tag: "td", style: {width:22, height:22, background: "#FFCCCC"}, events: {onclick: "settingsSetCaption('#FFCCCC')"}},
            {tag: "td", style: {width:22, height:22, background: "#CCCCFF"}, events: {onclick: "settingsSetCaption('#CCCCFF')"}},
          ]
        }
      }}
]



function Widget() {

    this.defaultProfile = {
        title: "Jaws widget",
        titleColor: ""
    }

    this.defaultPosition = {
        left: 100,
        top: 100,
        width: 300,
        height: 300,
        zIndex: 1000
    }

    this.init = function() {
        this.elements = {};
        this.id = null;
        this.isReduced = false;
        this.isSettingsReduced = true;
        this.profile = {};

        this.domModel = { tag: "div", className: "panel", id: "window",
                          childs: {
                          caption: { tag: "div", className: "caption", id: "caption",
                            childs: {
                            caption_table: { tag: "table", className: "sys_table", width: "100%",
                              childs: {
                              caption_tr: { tag: "tr",
                                childs: {}
                              }}
                            }}},
                          settings: { tag: "div", className: "settings", id: "settings" },
                          content: { tag: "div", id: "content" }
                          }
                        }

        }
    this.init();





    this.open = function(parent, id, profile) {
        for(c in cfgWidget) {
            if(typeof(this.cfg[c]) == "undefined") {
                this.cfg[c] = cfgWidget[c];
            }
        }

        if(this.cfg.isWindow) {
//            this.domModel.className = "window_div";
        }


        if(this.id == null) {
            this.id = (id) ? id : kernel.getUniqueId();
        }

        if(this.cfg.hasProfile) {
            profiler.addWidget(this);
            if(profile) {
                for(p in profile) {
                    this.profile[p] = profile[p];
                }
            }
        }


        this.buildWindow(parent);

        if(this.cfg.isWindow) {
            setElPosition(this.elements.window, this.position);
            this.setZIndex(this.position.zIndex);
        } else {
            if(this.elements["window"]) {
                this.elements.window.style.height = "100%";
            }
        }

        if(this.elements.window) {
            this.elements.window.wid = this.id;
        }

        this.buildInterface();

        if(this.elements.title) {
            this.elements.title.innerHTML = this.cfg.title;
        }

        kernel.addWidget(this);
        this.onOpen();
    }


    this.setParent = function(parentEl) {
        this.elements.window.parentNode.removeChild(this.elements.window);
        parentEl.appendChild(this.elements.window);
    }


    this.setZIndex = function(z) {
        this.elements.window.style.zIndex = z;
        if(desktop.maxZIndex < z) {
            desktop.maxZIndex = z;
        }
    }



    this.buildWindow = function(parent) {

        this.domModel.display = !this.cfg.isOpenHidden;

        with(this.domModel.childs.caption.childs.caption_table.childs.caption_tr) {
            if(this.cfg.hasIcon) {
                childs.icon_td = { tag: "td", width: 18,
                                   childs: [{tag: "img", id: "icon", src: "widgets/"+this.cfg.module.toLowerCase()+"/ico.gif"}] };
            }

            childs.title = { tag: "td", width: "100%",
                             childs: [{ tag: "div", align: "left", id: "title", className: "caption_title"}] };

            if(this.cfg.hasRefreshBtn) {
                childs.refresh_td = { tag: "td", width: 18,
                                      childs: [ createButtonDom(false, "refresh()", theme.icons.refresh) ]
                                    }

            }

            if(this.cfg.hasSettingsBtn) {
                childs.settings_td = { tag: "td", width: 18,
                                       childs: [ createButtonDom("<b>edit</b>", "switchSettings()") ]
                                     };
            }

            if(this.cfg.hasCloseBtn) {
                childs.close_td = { tag: "td", width: 18,
                                      childs: [ createButtonDom(false, "close()", theme.icons.close) ]
                                  };
            }
        }




        if(this.cfg.hasSizeBtn) {
            this.domModel.childs.status =
                { tag: "div", className: "window_status",
                  childs: [
                    { tag: "div", className: "window_size", id: "size_btn"}
                  ]}
        }

        this.domModel.childs.content.className = this.cfg.isWindow ? "window_content" : "content";

        this.buildDomModel(parent, this.domModel);
    }


    this.buildInterface = function() {
        if(this.cfg.hasDrag) {
            this.elements.caption.style.cursor = 'move';
            this.elements.window.drag = this.elements.size_btn ?
                                        new Drag(this.elements.window, this.elements.caption, this.elements.size_btn)
                                        :
                                        new Drag(this.elements.window, this.elements.caption);
        }


        if(this.cfg.hasSettingsBtn) {
            this.buildDomModel(this.elements.settings, domTitleSettings);
        }

//        this.settingsSetCaption(this.profile.titleColor);
        this.onBuildInterface();
        this.resizeContent();
    }


    this.close = function() {
        var flag = this.cfg.hasOnCloseConfirm ? confirm('You realy want to close '+this.cfg.title+' ?') : true;

        if(flag) {
            kernel.freeWidget(this.id);
            this.onClose();
            if(this.elements.window.parentNode) {
                this.elements.window.parentNode.removeChild(this.elements.window);
            }
            this.elements.window.innerHTML = '';
            this.elements.window = null;

            this.profile = false;
            this.save();
        }
    }


    this.resizeContent = function() {
        if(this.cfg.isWindow) {
            this.elements.content.style.width = (this.elements.window.offsetWidth-10) + "px";
            this.elements.content.style.height = (this.elements.window.offsetHeight-45) + "px";
        }
    }

    this.putOnTop = function() {
        desktop.maxZIndex++;
        this.elements.window.style.zIndex = desktop.maxZIndex;
    }


    this.setTitle = function(html) {
        this.elements.title.innerHTML = html;
    }


    this.switchSize = function() {
        if(this.isReduced) {
            hideEl(this.elements.btn_show);
            showEl(this.elements.btn_hide);
            showEl(this.elements.content);
        } else {
            hideEl(this.elements.btn_hide);
            showEl(this.elements.btn_show);
            this.hideSettings();
            hideEl(this.elements.content);
        }
        this.isReduced = !this.isReduced;
    }


    this.switchSettings = function() {
        if(this.isSettingsReduced) {
            this.showSettings();
        } else {
            this.hideSettings();
        }
        this.isSettingsReduced = !this.isSettingsReduced;
    }


    this.showSettings = function() {
        this.onShowSettings();
        showEl(this.elements.settings);
    }


    this.hideSettings = function() {
        if(this.elements.settings) {
            hideEl(this.elements.settings);
        }
    }

    this.getSignature = function() {
        return this.id;
    }


    this.clearEvent = function(el, name) {
        if(mozilla_nav) {
            el.setAttribute(name, "");
        } else {
            el[name] = "";
        }
    }

    this.assignEvent = function(el, name, callBack) {
        if(mozilla_nav) {
            el.setAttribute(name, "kernel.getWidget("+this.id+")."+callBack+";");
        } else {
            el[name] = new Function("kernel.getWidget("+this.id+")."+callBack+";");
        }
    }

    this.buildDomModel = function(parentEl, data) {
        if(data['tag']) {
            var el = document.createElement(data.tag);
            for (p in data) {
                switch(p) {
                    case null, "tag", "childs":
                    break;

                    case "id":
                        if(data.id) {
                            this.elements[data.id] = el;
                            el.id = data.id;
                        }
                        break;

                    case "cn":
                        el.className = data[p];
                        break;

                    case "html":

                        el.innerHTML = data[p];

                        break;

                    case "style":

                        for(var s in data.style) {
                            // debug here when IE error!!!!
                            // varp(data.style);
                            el.style[s] = data.style[s];


                        }
                        break;


                    case "options":
                        for(var i in data.options) {
                            el.options.add(new Option(data.options[i].text, data.options[i].value));
                        }
                        break;

                    case "src":
                        el.setAttribute("src", data.src);
                        if(data.tag == "img") {
                            var img = new Image();
                            img.src = data.src;
                        }
                        break;

                    case "display":
                        if(!data[p]) {
                            el.style.display = 'none';
                        }
                        break;

                    case "href":
                        if(data.events && data.events.onclick) {
                            data.href = "void";
                        }
                        el.href = "javascript:"+ ((data.href == "void") ? "void(0);" : "kernel.getWidget("+this.id+")."+data.href+";");
                        break;

                    case "sysHref":
                        el.href = data.sysHref;
                        break;

                    case "events":
                        var wid = this.id;

                        if(typeof(data.events) == "object") {
                            for(var e in data.events) {
                                this.assignEvent(el, e, data.events[e]);
                            }
                        }
                        break;

                    case "sysEvents":
                        if(typeof(data.sysEvents) == "object") {
                            for(var e in data.sysEvents) {

                                // by scam,  the best variant :)
                                if (!mozilla_nav) {
                                    el[e] = new Function(data.sysEvents[e]+";");
                                }
                                else {
                                    el.setAttribute(e, data.sysEvents[e]+";");
                                }

                            }
                        }
                        break;

                    default:
                        el[p] = data[p];
                        break;
                }
            }

            parentEl.appendChild(el);

            if(data.tag == "table") {
                parentEl = el;
                var el = document.createElement("tbody");
                if(data.id) {
                    this.elements[data.id+"_tbody"] = el;
                }
                parentEl.appendChild(el);
            }

            if(data.childs) {
                this.buildDomModel(el, data.childs);
            }

        } else {
            for(var e in data) {
                this.buildDomModel(parentEl, data[e]);
            }
        }
    }



    this.show = function() {
        if(this.elements.content) {
            showEl(this.elements.content);
        }
        this.onShow();
    }


    this.hide = function() {
        if(this.elements.content) {
            hideEl(this.elements.content);
        }
        this.hideSettings();
        this.onHide();
    }


/*
    this.settingsSetTitle = function() {
        this.profile.title = trim(this.elements.input_title.value);
        this.setTitle(this.profile.title);
        this.save();
    }

    this.settingsSetCaption = function(color) {
        this.elements.caption.style.backgroundColor = color;
        this.profile.titleColor = color;
        this.save();
    }
*/

    this.save = function() {
        profiler.saveProfile(this);
    }


    this.savePosition = function() {
        with (this.elements.window) {
            this.position = {
                left: offsetLeft,
                top: offsetTop,
                width: offsetWidth,
                height: offsetHeight,
                zIndex: style.zIndex
            }
        }
        profiler.savePosition(this);
    }



    this.onOpen = function() {}
    this.onBuildInterface = function() {}
    this.onClose = function() {}
    this.onShow = function() {}
    this.onHide = function() {}
    this.onShowSettings = function() {}
    this.onDrag = function() {}
    this.onSelectColor = function(target, color) {}
    this.onSelectFont = function(target, font) {}
    this.onSelectFontSize = function(target, fontSize) {}

    this.timerHandler = function() {}
    this.refresh = function() {}
    this.dispatchMsg = function() {}

    this.hidePopup = function(elIdx) {
        hideEl(this.elements[elIdx]);
    }







    this.buildPopupLink = function(title, img, popupName) {
    }


    this.activePopupName = null;
    this.showPopup = function(name) {
        if(this.activePopupName) {
            hideEl(this.elements[this.activePopupName]);
        }
        showEl(this.elements[name]);
        this.activePopupName = name;
    }


    this.hidePopup = function(name) {

    }



/********************************************************************************
 *
 *  POPUPS
 *
 */


    this.activePopup = null;

    this.showPopupAtLink = function(name) {
        var widx = name + "_window";
        var lidx = name + "_link";
        if(this.elements[widx]) {
//            if(!this.elements[idx].is_alone) {
                this.hideActivePopup();
                this.activePopup = name;
//            }
            showEl(this.elements[widx]);
            var pos = getElPos(this.elements[lidx]);
            pos.top += 16;

            wrect = getWindowRect();

            if(pos.left + this.elements[widx].offsetWidth > wrect.width) {
                pos.left = wrect.width - this.elements[widx].offsetWidth - 15;
            }

            if(pos.top + this.elements[widx].offsetHeight > wrect.height) {
                pos.top = wrect.height - this.elements[widx].offsetHeight - 15;
            }

            setElRect(this.elements[widx], pos);
            desktop.putElOnTop(this.elements[widx]);
        } else {
            this.showError("Popup \""+name+"\" does't exists.");
        }
    }


    this.showPopup = function(name) {
        var widx = name + "_window";
        if(this.elements[widx]) {
//            if(!this.elements[idx].is_alone) {
                this.hideActivePopup();
                this.activePopup = name;
//            }
            showEl(this.elements[widx]);

            wrect = getWindowRect();
            with(this.elements[widx].style) {
                left = wrect.left + Math.round((wrect.width - this.elements[widx].offsetWidth) * 0.5) + "px";
                top = wrect.top + Math.round((wrect.height - this.elements[widx].offsetHeight) * 0.4) + "px";
            }
            desktop.putElOnTop(this.elements[widx]);

            showEl(desktop.elements["screen_block"]);
            setElRect(desktop.elements["screen_block"], wrect);
            desktop.elements["screen_block"].style.zIndex = this.elements[widx].style.zIndex - 1;
        } else {
            this.showError("Popup \""+name+"\" does't exists.");
        }
    }


    this.hidePopup = function(name) {
        var idx = name + "_window";
        if(this.elements[idx]) {
            if(!this.elements[idx].is_alone) {
                this.activePopup = null;
            }
            hideEl(this.elements[idx]);
            hideEl(desktop.elements["screen_block"]);
        }
    }

    this.hideActivePopup = function() {
        if(this.activePopup) {
            hideEl(this.elements[this.activePopup + "_window"]);
            hideEl(desktop.elements["screen_block"]);
            this.activePopup = null;
        }
    }


    this.createPopupLink = function(parentEl, p) {
        var lp = clone(p);
        lp.id = lp.name + "_link";
        lp.action = "showPopup('"+p.name+"')";
        this.buildDomModel(parentEl, createLinkDom(lp));
        this.buildDomModel(document.body, createPopupDom(p));
    }



/********************************************************************************
 *
 *  MENUS
 *
 */
    this.activeMenuItem = null;
    this.activeMenu = null;

    this.selectMenuItem = function(idx) {
        if(this.activeMenuItem) {
            this.unselectMenuItem(this.activeMenuItem);
            this.activeMenuItem = null;
        }
        this.elements[idx].className = "menu_item_selected";
        this.activeMenuItem = idx;
    }

    this.unselectMenuItem = function(idx) {
        this.elements[idx].className = "menu_item";
    }

    this.unselectActiveMenuItem = function() {
        if(this.activeMenuItem) {
            this.unselectMenuItem(this.activeMenuItem);
            this.activeMenuItem = null;
        }
    }


    this.showMenu = function(name, pos) {
        this.hideActiveMenu();

        var idx = name + "_menu";
        showEl(this.elements[idx]);

        wrect = getWindowRect();

        if(pos.left + this.elements[idx].offsetWidth > wrect.width) {
            pos.left = wrect.width - this.elements[idx].offsetWidth - 15;
        }

        if(pos.top + this.elements[idx].offsetHeight > wrect.height) {
            pos.top = wrect.height - this.elements[idx].offsetHeight - 15;
        }

        setElRect(this.elements[idx], pos);

        desktop.putElOnTop(this.elements[idx]);
        this.activeMenu = name;
    }

    this.hideActiveMenu = function() {
        if(this.activeMenu) {
            this.unselectActiveMenuItem();
            hideEl(this.elements[this.activeMenu + "_menu"]);
            this.activeMenu = null;
        }
    }



/********************************************************************************
 *
 *  ERRORS
 *
 */


    this.showError = function(text) {
        alert("Error in widget <"+this.cfg.module+">\n"+text);
    }






/********************************************************************************
 *
 *  ELEMENTS
 *
 */
    this.hideElement = function(idx) {
        hideEl(this.elements[idx]);
    }


    this.showElement = function(idx) {
        showEl(this.elements[idx]);
    }


    this.getInputValue = function(idx, notrim) {
        var v = this.elements[idx].value;
        return notrim ? v : trim(v);
    }
}