/****************************************************************************/
/*
 * Larry's Web Components (LWC)
 */
/****************************************************************************/

var MSIE = navigator.userAgent.indexOf("MSIE") > -1;

var BUTTON_EXTRA_PADDING = 0;
if (MSIE) {
    BUTTON_EXTRA_PADDING = 2;
}

function setOpacity(elem, percent)
{
    if (MSIE) {
        elem.style.filter = "alpha(Opacity=" + percent + ")";
    } else {
        elem.style.opacity = percent / 100;
    }
}

Function.prototype.derives = function(parent) 
{
    for(var key in parent.prototype) {
        this.prototype[key] = parent.prototype[key];
    }
}

/****************************************************************************/

function LRenderQueue()
{
    this.queue = new Array();
    var instance = this;
    var handler = function() {
        for(var i = 0; i < instance.queue.length; i++) {
            if (!instance.queue[i]._rendered) {
                instance.queue[i].checkFullyLoaded();
            }
        }
    };
    setInterval(handler, 100);
}

LRenderQueue.prototype.add = function(component)
{
    this.queue.push(component);
}

LRenderQueue.prototype.remove = function(component)
{
    for(var i = 0; i < this.queue.length; i++) {
        if (this.queue[i] == component) {
            this.queue.splice(i, 1);
            return 0;
        }
    }
}

var s_renderQueue = new LRenderQueue();

/****************************************************************************/

function LObject()
{
    // nothing really
}

/****************************************************************************/

function LComponent(id) 
{
    LObject.apply(this);
    this.id = id;
    this.numImagesToLoad = 0;
    this.numImagesLoaded = 0;
    this.numChildrenLoaded = 0;
    this.children = new Array();
    this.images = new Array();
    this.parent = null;
    this.enabled = true;
    this.style = null;
    
    this._rendered = false;
    s_renderQueue.add(this);
}

LComponent.derives(LObject);

LComponent.prototype.addImageToLoad = function(src)
{
    var instance = this;
    var img = new Image();
    img.src = src;
    img.onload = function() { instance.onImageLoaded() };
    this.numImagesToLoad++;
    this.images.push(img);
    return img;
}

LComponent.prototype.render = function()
{
    // override this
}

LComponent.prototype.renderAll = function()
{
    if (this._rendered) {
        return;
    }

    if (MSIE && !(document.readyState == 4 || document.readyState == "complete")) {
        var instance = this;
        setTimeout(function() { instance.renderAll() }, 100);
    }

    this.render();
    this.applyStyle();
    this._rendered = true;
    s_renderQueue.remove(this);
    if (this.parent) {
        this.parent.getContainerElement().appendChild(this.getRootElement());
    } 
    for(var i = 0; i < this.children.length; i++) {
        this.children[i].renderAll();
    }
}

LComponent.prototype.getRootElement = function()
{
    return this.element;
}

LComponent.prototype.setRootElement = function(element)
{
    this.element = element;
}

LComponent.prototype.getContainerElement = function()
{
    return this.getRootElement();
}

LComponent.prototype.setContainerElement = function(element)
{
    this.setRootElement(element);
}

LComponent.prototype.addChild = function(child)
{
    this.children.push(child);
    child.parent = this;
}

LComponent.prototype.onImageLoaded = function()
{
    this.numImagesLoaded++;
    this.checkFullyLoaded();
}

LComponent.prototype.onChildLoaded = function(who)
{
    this.numChildrenLoaded++;
    this.checkFullyLoaded();
}

LComponent.prototype.checkFullyLoaded = function() 
{
    if (this.numImagesLoaded == this.numImagesToLoad && this.numChildrenLoaded == this.children.length) {
        if (this.parent) {
            // notify parent of this fully loaded child
            this.parent.onChildLoaded(this);
        } else {
            // in case of root, start rendering down
            this.renderAll();
        }
    }
}

LComponent.prototype.setEnabled = function(enabled)
{
    this.enabled = enabled;
    if (this.getRootElement()) {
        setOpacity(this.getRootElement(), (this.getEnabled()) ? 100 : 10);
    }        
}

LComponent.prototype.getEnabled = function()
{
    return this.enabled;
}

LComponent.prototype.setVisible = function(visible)
{
    this.visible = visible;
    this.getRootElement().style.display = visible ? 'block' : 'none';
}

LComponent.prototype.getVisible = function()
{
    return this.visible;
}

LComponent.prototype.setStyle = function(style)
{
    this.style = style;
}

LComponent.prototype.getStyle = function()
{
    return this.style;
}

LComponent.prototype.applyStyle = function()
{
    var root = this.getRootElement();
    if (this.style && root) {
        for(var key in this.style) {
            root.style[key] = this.style[key];
        }
    }
}

/****************************************************************************/

// xxx/yyy.gif@0,38:25x38
function LImage(id, src, clip)
{
    LComponent.call(this, id);
    this.clip = clip;    
    this.src = src;
    this.imgElem = null;
    this.addImageToLoad(this.src);
}

LImage.derives(LComponent);

LImage.prototype.setClip = function(clip) 
{
    this.clip = clip;
    var view = this.getRootElement();
    if (view) {
        view.style.overflow = 'hidden';
        view.style.width = this.clip.width + 'px';
        view.style.height = this.clip.height + 'px';
        this.imgElem.style.marginLeft = -1 * this.clip.x + 'px';
        this.imgElem.style.marginTop = -1 * this.clip.y + 'px';
    }
}

LImage.prototype.getClip = function()
{
    return this.clip;
}

LImage.prototype.render = function()
{
    var view = document.createElement("DIV");
    var img = document.createElement("IMG");
    img.src = this.src;
    if (this.clip) {
        view.style.overflow = 'hidden';
        view.style.width = this.clip.width + 'px';
        view.style.height = this.clip.height + 'px';
        img.style.marginLeft = -1 * this.clip.x + 'px';
        img.style.marginTop = -1 * this.clip.y + 'px';
    }
    view.appendChild(img);
    this.imgElem = img;
    this.setRootElement(view);
}

/****************************************************************************/

function LTag(id, tag, html, className, style)
{
    LComponent.call(this, id);
    this.tag = tag;
    this.html = html;
    this.className = className;
    this.style = style;
}

LTag.derives(LComponent);

LTag.prototype.render = function()
{
    var div = document.createElement(this.tag);
    if (this.html) {
        div.innerHTML = this.html;
    }
    if (this.className) {
        div.className = this.className;
    }
    if (this.style) {
        for(var key in this.style) {
            div.style[key] = this.style[key];
        }
    }
    this.setRootElement(div);
}

/****************************************************************************/

function LStage(id)
{
    LComponent.call(this, id);
}

LStage.derives(LComponent);

LStage.prototype.render = function()
{
    this.setRootElement(document.getElementById(this.id));
}

LStage.prototype.renderAll = function()
{
    LComponent.prototype.renderAll.call(this);
}

/****************************************************************************/

function LContainer(id, layout)
{
    LComponent.call(this, id);
    this.layout = layout;
}

LContainer.derives(LComponent);

LContainer.prototype.render = function()
{
    var div = document.createElement("DIV");
    div.id = this.id;
    this.setRootElement(div);
}

/****************************************************************************/

function LPopup(id, x, y, width, height)
{
    LContainer.call(this, id);
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
}

LPopup.derives(LContainer);

LPopup.prototype.render = function()
{
    // call super constructor
    LContainer.prototype.render.call(this);
    
    // modify root element
    var root = this.getRootElement();    
    this.visible = false;
    root.style.display = 'none';
    root.style.zIndex = 100;
    root.style.top = this.y + "px";
    root.style.left = this.x + "px";
    root.style.position = 'absolute';
    if (this.width) {
        root.style.width = this.width + "px";
    }
    if (this.height) {
        root.style.height = this.height + "px";
    }
    if (this.style.background) {
        root.style.background = this.style.background;
    }
    root.style.border = "solid #333333 1px";
    root.style.padding = "3px";
}

/****************************************************************************/

function LButton(id, srcs) 
{
    LComponent.call(this, id);
    this.imageIndex = 0;
    if (typeof(srcs) == "string") {
        this.srcs = [ srcs ];
    } else {
        this.srcs = srcs;
    }
    for(var i = 0; i < this.srcs.length; i++) {
        this.addImageToLoad(this.srcs[i]);
    }
}

LButton.derives(LComponent);

LButton.prototype.render = function()
{
    var instance = this;
    var img = document.createElement("IMG");
    img.id = this.id;
    img.src = this.srcs[this.imageIndex];
    img.style.padding = 2 + BUTTON_EXTRA_PADDING;
    img.style.margin = 2;
    img.onmouseover = function() {
        if (instance.enabled) {
            img.style.borderLeft = img.style.borderTop = "solid #EEEEEE 1px";
            img.style.borderRight = img.style.borderBottom = "solid #999999 1px";
            img.style.margin = 1;
        }
    }
    img.onmouseout = function() {
        img.style.border = "";
        img.style.margin = 2;
    }
    img.onmousedown = function() {
        if (instance.enabled) {
            img.style.borderLeft = img.style.borderTop = "solid #999999 1px";
            img.style.borderRight = img.style.borderBottom = "solid #EEEEEE 1px";
            img.style.marginLeft = img.style.marginTop = 2;
            img.style.marginRight = img.style.marginBottom = 0;
        }
    }
    img.onmouseup = img.onmouseover;
    img.style.cursor = "pointer";
    setOpacity(img, (this.getEnabled()) ? 100 : 10);
    img.onclick = function() { 
        if (instance.enabled) {
            instance.onClick() 
        }
    }

    this.setRootElement(img);   
}

LButton.prototype.getImageCount = function()
{
    return this.srcs.length;
}

LButton.prototype.setImageIndex = function(imageIndex)
{
    this.imageIndex = imageIndex;
    this.element.src = this.srcs[this.imageIndex];
}

LButton.prototype.getImageIndex = function()
{
    return this.imageIndex;
}

LButton.prototype.onClick = function()
{
    // does nothing
}

LButton.prototype.setEnabled = function(value)
{
    LComponent.prototype.setEnabled.call(this, value);    
    if (this.element) {
        setOpacity(this.element, (this.getEnabled()) ? 100 : 10);
    }        
}

/****************************************************************************/

functin LPanel(id, title)
{
	LComponent.call(this, id);
	this.title = title;
}

LPanel.derives(LComponent);

LPanel.prototype.render = function()
{
	var div = document.createElement("DIV");
	div.id = this.id;
	this.setRootElement(div);
}
