var TreeConstants = {
    CLASS_NAME_SELECTED_NODE : "selected",
    CLASS_NAME_NODE_TEXT : "nodeText",
    CLASS_NAME_NODE_CHILDS_CONTAINER : "childsContainer",

    TAG_NAME_NODE : "div",



    ATTRIBUTE_NAME_NODE_EXPANDED : "expanded",

    ATTRIBUTE_NAME_CHECK_NAME : "checkName",
    ATTRIBUTE_NAME_CHECK_VALUE : "checkValue",
    ATTRIBUTE_NAME_CHECK_CHECKED  : "checked",
    ATTRIBUTE_NAME_CHECK_DISABLED : "checkDisabled",
    ATTRIBUTE_NAME_CHECK_ALL : "checkAll"
}


function TreeNode ( oTree, oText, oPlus, oDivNode, oCheckInput, oParentNode){
    //interface objects
    this.oTree = oTree;
    this.oText  = oText;
    this.oPlus = oPlus;
    this.oDivNode = oDivNode;
    this.oCheckInput = oCheckInput;

    //obiecte structura interna arbore
    this.oParentNode = oParentNode;
    this.childNodes = [];

    var onSelect = oDivNode.getAttribute("onSelect");
    if( onSelect ){
        this.onSelect = new Function( onSelect );
    }
}

function StaticTree( treeContainerId, highLightSelected, checkOnSelected, onCheckInputClicked){
    this.treeContainerId = treeContainerId;
    this.oDiv = $( this.treeContainerId);
    this.highLightSelected = highLightSelected;
    this.checkOnSelected = checkOnSelected
    this.onCheckInputClicked = onCheckInputClicked;

    this.init();
}

TreeNode.prototype = {
    select : function(){
        this.oText.className = TreeConstants.CLASS_NAME_SELECTED_NODE;
        this.onSelect();
    },

    deselect : function(){
        this.oText.className = TreeConstants.CLASS_NAME_NODE_TEXT;
    },

    onClickTextHandler : function(){
        this.oTree.nodeSelected( this);    //notify treeControl about click event on "Node Text"

        if( this.oCheckInput && this.oTree.checkOnSelected && !this.oCheckInput.disabled ) { //check/uncheck asociated checkbox input
            this.oCheckInput.checked = !this.oCheckInput.checked;

            //simulate the click event
            this.onClickCheckInputHandler();

            //recursive check/uncheck childs ...
            this.checkUncheckChilds( this, this.oCheckInput.checked);
        }
    },

    checkUncheckChilds : function ( node, checked){
//        var str = "";
//        for (var i = 0; i < node.childNodes.length; i++){
//            str += node.childNodes[i].oCheckInput.value + " ";
//        }
//        alert( "Childs: " + str);
        
        for (var i = 0; i < node.childNodes.length; i++){
            var n = node.childNodes[i];
            if( n.oCheckInput && n.oCheckInput.checked != checked){
                n.oCheckInput.checked = checked;

                //simulate Event, do not set selected style
                this.oTree.onInputClicked( n, false);
            }

            //recursive for childs
            this.checkUncheckChilds( n, checked);
        }
    },

    expandParent : function (){
        var parentNode = this.oParentNode;
        if( parentNode && parentNode.oPlus.getStatus() == PlusConstants.STATUS_PLUS){
            parentNode.oPlus.setMinus();
            parentNode.expandParent( );
        }
    },

    onClickCheckInputHandler : function(){
        this.oTree.onInputClicked( this, true);

        if( this.oCheckInput.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_ALL) && this.oParentNode){

            this.checkUncheckChilds( this.oParentNode, this.oCheckInput.checked);
        }else{
            this.checkUncheckChilds( this, this.oCheckInput.checked);
        }
    },

    withPlus : function(){
        return this.oPlus.obj.style.visibility != "hidden";
    },

    onSelect : function(){}
}

StaticTree.prototype = {
    selectedNode : null,
    rootDiv : null,
    plusCounter : 0,
    nodes : [],
    init : function(){
        this.rootDiv = document.createElement("div");
        this.rootDiv.innerHTML = this.oDiv.innerHTML;
        this.oDiv.innerHTML = "";
        this.oDiv.appendChild( this.rootDiv);

        var childs = this.getChildNodes( this.rootDiv);
        for(var i = 0; i < childs.length; i++){
            this.initNode( childs[i], null);
        }
    },

    createCheckInput : function ( oDiv){
        var checku = null;

        var type = null;
        if( (type = oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_NAME)) != null){
            checku = document.createElement("input");
            checku.type = "checkbox";
            checku.name = oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_NAME);
            checku.value = oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_VALUE);
            checku.id = "checku"+this.nodes.length + 1;

            checku.setAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_ALL, oDiv.getAttribute(TreeConstants.ATTRIBUTE_NAME_CHECK_ALL));
        }
        return checku;
    },

    initNode : function ( oDiv, parentNode){
        var oTextNode = this.getTextNode( oDiv);
        var oChildsNode = this.getChildsContainer( oDiv);

        if( oTextNode == null) return;

        var textSpan = document.createElement("span");
        textSpan.innerHTML = oTextNode.innerHTML;

        oTextNode.innerHTML = "";

        var oCheckInput = this.createCheckInput( oDiv); //null daca nu are check Input

        //plus ...
        this.plusCounter++;
        var plusSpan = document.createElement("span");
        plusSpan.id  = "plus" + this.plusCounter;
        oTextNode.appendChild( plusSpan);

        if( oChildsNode) oChildsNode.id = "childsContainer"+this.plusCounter;

        var oPlus = new Plus( plusSpan.id, oChildsNode ? oChildsNode.id : null);

        if( "true" == oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_NODE_EXPANDED)){
            oPlus.setMinus();
        }

        if ( oChildsNode){
            plusSpan.style.visibility = "";
        }else{
            plusSpan.style.visibility = "hidden";
        }
        //...plus

        var node = new TreeNode( this, textSpan, oPlus, oDiv, oCheckInput, parentNode);

        if( oChildsNode){
            var childs = this.getChildNodes( oChildsNode);
            for(var i = 0; i < childs.length; i++){
                node.childNodes.push( this.initNode( childs[i], node));
            }
        }

        textSpan.onclick = node.onClickTextHandler.bindAsEventListener( node);
        if( oCheckInput != null) {
            oTextNode.appendChild( oCheckInput);

            //check ...{
            var checked = oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_CHECKED);
            if( checked && "true" == checked.toLowerCase()){
                oCheckInput.checked = true;
                node.expandParent();
                if( node.withPlus()) node.oPlus.setMinus();
            }
            oCheckInput.disabled = ("true" == oDiv.getAttribute( TreeConstants.ATTRIBUTE_NAME_CHECK_DISABLED));
            //}
            
            oCheckInput.onclick = node.onClickCheckInputHandler.bindAsEventListener( node);
        }
        
        oTextNode.appendChild( textSpan);
        return node;
    },

    getTextNode : function (oDiv){
//        try{
//            return document.getElementsByClassName( TreeConstants.CLASS_NAME_NODE_TEXT, oDiv)[0];
//        }catch (e){
//            return null;
//        }
        var result = null;
        try{
            var arr = oDiv.childNodes;
            for( var i = 0; i < arr.length; i++){
                if( arr[i].className == TreeConstants.CLASS_NAME_NODE_TEXT){
                    result = arr[ i];
                    break;
                }
            }
        }catch (e){
        }
        return result;
    },

    getChildsContainer: function (oDiv){
//        try{
//            return document.getElementsByClassName( TreeConstants.CLASS_NAME_NODE_CHILDS_CONTAINER, oDiv)[0];
//        }catch (e){
//            return null;
//        }
        var result = null;
        try{
            var arr = oDiv.childNodes;
            for( var i = 0; i < arr.length; i++){
                if( arr[i].className == TreeConstants.CLASS_NAME_NODE_CHILDS_CONTAINER){
                    result = arr[ i];
                    break;
                }
            }
        }catch (e){
        }
        return result;
    },
    
    getChildNodes : function(oDiv){
        try{
            var result = [];
            var arr = oDiv.childNodes;
            for( var i=0; i < arr.length; i++){
                if( arr[i].tagName  && arr[i].tagName.toLowerCase() == TreeConstants.TAG_NAME_NODE){
                    result.push( arr[i]);
                }
            }
            return result;
        }catch (e){
            return null;
        }
    },

    setNodeStyle : function ( node){
        if( this.highLightSelected && this.selectedNode != node){
            if( this.selectedNode) {
                this.selectedNode.deselect();
            }

            this.selectedNode = node;

            this.selectedNode.select();
        }
    },

    //events{
    nodeSelected : function ( node){
        this.setNodeStyle( node);
    },

    onInputClicked : function ( node, setStyle){
        if( setStyle) this.setNodeStyle( node);

        if( node.oCheckInput.checked) {
            //expand childs container to show all checked inputs
            if( node.oPlus && node.oPlus.getStatus() == PlusConstants.STATUS_PLUS){
                node.oPlus.setMinus();
            }
            
            this.inputChecked( node);
        }else{
            this.inputUnchecked( node);
        }

        //notify user...
        if( this.onCheckInputClicked && this.onCheckInputClicked instanceof Function) this.onCheckInputClicked( node);
    },

    inputChecked : function ( node){
//        alert("TreeControl inputChecked :" + node.oCheckInput.value + " " + node.oCheckInput.checked);
    },

    inputUnchecked : function ( node){
//        alert("TreeControl inputUnchecked :" + node.oCheckInput.value + " " + node.oCheckInput.checked);
    }
    //}events
}