/*
  copyright (c) 2003 Jan-Klaas Kollhof
 
  This is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
 
  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this software; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
*/


svgui.components = function(){
    const Focused = 2;
    const ChildFocused = 1;
    const NoFocus = 0;
    
    var ChildAddedEvent = function(child){
        this.type = "childAdded";
        this.child = child;
    }
    
    var PositionChangedEvent = function(){
        this.type = "positionChanged";
    }
    
    var FocusChangedEvent = function(){
        this.type = "focusChanged";
    }
    
    var BroughtToFrontEvent = function(){
        this.type = "broughtToFront";
    }
    
    var TextChangedEvent = function(){
        this.type = "textChanged";
    }
    
    var SelectionChangedEvent = function(){
        this.type = "selectionChanged";
    }
    
    var ActivateEvent = function(active){
        this.type = "activate";
        this.active = active;
    }
    
    //-------------------------------------------------------Generic------------------------------------
    
    var Generic = function(){
        var Super = Object ;
        var Generic = newClass(Super);
        
        Generic.prototype.init = function(name, x, y, width, height){
            this.parent = null;
            this.listeners = new Array();
            this.dragable = false;
            this.name = name;
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.children = new Array();
            this.focusedChild = null;
            this.focusState = 0;
            this.applyTheme();
        }
        
        Generic.prototype.applyTheme = function(){
            svgui.themeManager.applyTheme(this, "Generic");
        }
        
        Generic.prototype.addEventListener = function(type, listener){
            if (this.listeners[type]){
                this.listeners[type].push(listener);
            }else{
                this.listeners[type] = new Array(listener);
            }
        }
        
        Generic.prototype.removeEventListener = function(type, listener){
            if (this.listeners[type]){
                var l = this.listeners[evt.type];
                for(var i = 0; i<l.length; i++){
                    if (l[i]  ==  listener){
                        l.splice(i, 1);
                        i = l.length;
                    }
                }
            }
        }
        
        Generic.prototype.fireEvent = function(evt){
            if (this.listeners[evt.type]){
                var l = this.listeners[evt.type];
                for(var i = 0; i<l.length; i++){
                    l[i].handleEvent(evt);
                }
            }
        }
        
        Generic.prototype.addChild = function(child){
            child.parent = this;
            this[child.name] = child;
            this.children.push(child);
            this.fireEvent(new ChildAddedEvent(child));
            return child;
        }
        
        Generic.prototype.setPosition = function(x, y){
            this.x = x;
            this.y = y;
            this.fireEvent(new PositionChangedEvent());
        }
        
        Generic.prototype.bringToFront = function(){
            this.fireEvent(new BroughtToFrontEvent());
        }
        
        Generic.prototype.dispatchFocus = function(value, newFocObj){
            switch(value){
                case NoFocus: 
                    if(this.focusedChild){
                        this.focusedChild.setFocus(NoFocus, newFocObj);
                    }
                    break;
                case ChildFocused:     
                    if(this.focusedChild){
                        if(this.focusedChild != newFocObj){
                            this.focusedChild.setFocus(NoFocus, newFocObj);
                            this.focusedChild = newFocObj;
                        }
                    }else{
                        this.focusedChild = newFocObj;
                    }
                    if(this.parent){
                        this.parent.setFocus(ChildFocused, this);
                    }
                    break;
                case Focused:
                    if (this.focusedChild){
                        if(this.focusState == ChildFocused){
                            this.focusedChild.setFocus(NoFocus, this);
                        }else{
                            value = ChildFocused;
                            this.focusedChild.setFocus(Focused, this);
                        }
                    }else{
                        if(this.parent){
                            this.parent.setFocus(ChildFocused, this);
                        }
                    }
                    break;
            }
            this.focusState = value;
        }
        Generic.prototype.setFocus = function(value, newFocObj){
            this.dispatchFocus(value, newFocObj);
            
            if(this.focusState == Focused){
                svgui.inputManager.registerListener(this);
            }else{
                svgui.inputManager.unregisterListener(this);
            }
            this.fireEvent(new FocusChangedEvent());
        }
    
        Generic.prototype.handleEvent = function(evt){
            if(this[evt.type]){
                this[evt.type](evt);
            }
        }
            
        Generic.prototype.mousedown = function(evt){
            evt.stopPropagation();
            this.setFocus(Focused, this);
            this.activate(true);
            document.documentElement.addEventListener("mouseup", this, false);
            if(this.dragable){
                this.bringToFront();
                this.dragX = evt.screenX - this.x;
                this.dragY = evt.screenY - this.y;
                document.documentElement.addEventListener("mousemove", this, false);
            }
        }
        Generic.prototype.mouseup = function(evt){
            this.activate(false);
            document.documentElement.removeEventListener("mouseup", this, false);
            if(this.dragable){
                document.documentElement.removeEventListener("mousemove", this, false);
            }
        }
        Generic.prototype.mousemove = function(evt){
            if((evt.button == 0) && this.dragable){
                var newX = evt.screenX - this.dragX;
                var newY = evt.screenY - this.dragY;
                this.setPosition(newX, newY);
            }
        }
        Generic.prototype.activate = function(value){
            this.fireEvent(new ActivateEvent(value));
        }
        Generic.prototype.cycleChild = function(evt){
            if (this.children.length==0 || this.focusState == Focused){
                this.parent.cycleChild(evt);
            }else{
                for(var i=0;i<this.children.length;i++){
                    if(this.children[i] == this.focusedChild){
                        if(i+1 == this.children.length){
                            //this.setFocus(Focused, this);
                            this.parent.cycleChild(evt);
                        }else{
                            this.children[i+1].setFocus(Focused, this.children[i+1]);
                        }
                        i=this.children.length;
                    }
                }
            }
        }

        return Generic;
    }();
    
    
    
    //------------------------------------------------Frame------------------------------------------------------
    var Frame = function(){
        var Super = Generic;
        var Frame = newClass(Super);
        
        Frame.prototype.applyTheme = function(){
            svgui.themeManager.applyTheme(this, "Frame");
        }
        return Frame;
    }();
    
    
    //----------------------------------------------Button---------------------------------------
    var Button = function(){
        var Super = Frame;
        var Button = newClass(Super);

        Button.prototype.init = function(name, x, y, width, height){
            Super.prototype.init.call(this,name, x, y, width, height);
        }

        Button.prototype.applyTheme = function(){
            svgui.themeManager.applyTheme(this, "Button");
        }
        
        return Button;
    }();
    
      //-------------------------------------------DragableFrame-----------------------------------------------------------
    
    var DragableFrame = function(){
        var Super = Frame;
        var  DragableFrame = newClass(Super);

        DragableFrame.prototype.init = function(name, x, y, width, height){
            Super.prototype.init.call(this, name, x, y, width, height);
            this.dragable = true;
        }
        
        return DragableFrame;
    }();
    
     
    
    //--------------------------------------------------TextBox------------------------------------------------------
    
    var TextBox = function(){
        var Super = Frame;
        var TextBox = newClass(Super);
        
        TextBox.prototype.init = function(name, x, y, width, height){
            this.text  = "";
            this.selStart = 0;
            this.selLength = 0;
            Super.prototype.init.call(this, name, x, y, width, height);
        }
        
        TextBox.prototype.applyTheme = function(){
            svgui.themeManager.applyTheme(this, "TextBox");
        }
        
        TextBox.prototype.textInput = function(evt){
            this.replaceSelection(evt.data);
        }
        
        TextBox.prototype.deleteR = function(evt){
            if(this.selLength == 0){
                this.selLength = 1;
            }
            this.replaceSelection("");
        }
    
        TextBox.prototype.deleteL = function(evt){
            if((this.selStart > 0) && (this.selLength == 0)){
                this.selLength = -1;
            }
            this.replaceSelection("");
        }
        
        TextBox.prototype.navigate = function(evt){
            switch (evt.direction){
                case svgui.inputManager.navigateW:
                    this.onLeft();
                    break;
                case svgui.inputManager.navigateE:
                    this.onRight();
                    break;
            }
        }
        TextBox.prototype.onLeft = function(){
            this.selStart += this.selLength -1 ;
            this.selLength = 0;
            if(this.selStart<0){
                this.selStart = 0;
            }
            this.selectionChanged();
        }
        
        TextBox.prototype.onRight = function(){
            this.selStart += this.selLength + 1 ;
            this.selLength = 0;
            if(this.selStart>this.text.length){
                this.selStart = this.text.length;
            }
            this.selectionChanged();
        }
        
        TextBox.prototype.replaceSelection = function(str){
            this.text = this.getPreSelection() + str + this.getPostSelection();
            if(this.selLength<0){
                this.selStart += this.selLength + str.length;
            }else{
                this.selStart += str.length ;
            }
            this.selLength = 0;
            this.textChanged();
            this.selectionChanged();
        }
        
        TextBox.prototype.setText = function(text){
            this.text = text;
            this.selStart = text.length;
            this.selLength = 0;
            this.textChanged();
            this.selectionChanged();
        }
        
        TextBox.prototype.getSelection = function(){
            if(this.selLength<0){
                return this.text.slice(this.selStart + this.selLength,  this.selStart);
            }else{
                return this.text.slice(this.selStart, this.selStart + this.selLength);
            }
        }
        TextBox.prototype.getPreSelection = function(){
            if(this.selLength<0){
                return this.text.slice(0, this.selStart + this.selLength);
            }else{
                return this.text.slice(0, this.selStart);
            }
        }
        TextBox.prototype.getPostSelection =  function(){
            if(this.selLength<0){
                return this.text.slice(this.selStart, this.text.length);
            }else{
                return this.text.slice(this.selStart + this.selLength, this.text.length);
            }
        }
        
        TextBox.prototype.textChanged = function(){
            this.fireEvent(new TextChangedEvent());
        }
        
        TextBox.prototype.selectionChanged = function(){
            this.fireEvent(new SelectionChangedEvent());
        }        
        
        return TextBox;
    }();
    
        
    return {Frame:Frame, Button:Button, DragableFrame:DragableFrame, TextBox:TextBox};
}();