var TREE_V_ALIGN  = 'vAlign';
var TREE_H_ALIGN  = 'hAlign';

TreeSelect = iClass.create({
	onchange: function( Value, Select ) {},
  
  initialize: function( args ) {
    this.name         = args.name;
    this.title        = args.title || '';
    this.titles       = args.titles;
    this.xmlDoc       = args.xmlDoc;
    this.selects      = args.selects; // selects options with values
    this.emptyOption  = args.emptyOption;
    this.emptyOptions = args.emptyOptions;
    this.treeAlign    = args.treeAlign;
    this.width        = parseInt( args.width ) || 0;
		this.size         = args.size || 1;
    this.autoChoise   = args.autoChoise == true;

    this.selectElements = [];
    this.elementVisible = [];
    
    this.value  = ( this.emptyOption || this.emptyOptions ) ?  0  : null;
    this.xvalue = ( this.emptyOption || this.emptyOptions ) ? [0] : null;
    
    if ( this.titles && this.titles.length > 1 ) this.treeAlign = TREE_V_ALIGN;
    if ( this.xmlDoc ) {
      var parser   = new TreeSelectXML( this.xmlDoc );
      this.selects = parser.parse();
    } // if
  }, // initialize
  
  hasTitle: function() {
    return ( this.title != '' || ( this.titles && this.titles.length > 0 ) );
  }, // hasTitle
  
  markup: function() {
    try {
      var selects  = this.selects;
      var vAlign   = this.treeAlign == TREE_V_ALIGN;
      var hasTitle = this.hasTitle();
    
      var markupTable     = crTable();
      var markupTableBody = cr( 'TBODY' );
      var markupTR;
      var titleTD;
      var markupTD;
    
      markupTable.appendChild( markupTableBody );
    
      var maxOptionLen = 0;
      if ( this.width == 0 && vAlign ) {
        // поиск  самого длинного слова в значениях селекта
        for ( var i=0; i < selects.length; i++ ) {
          var options = selects[i].options;
          for ( var j=0; j < options.length; j++ ) {
            var len = options[j].value.length;
            if ( len > maxOptionLen ) maxOptionLen = len;
          } // for
        } // for
      } // if
    
      for ( var i=0; i < selects.length; i++ ) {
        var select;
      
        if ( i == 0 ) {
          select = this.fillSelect( null, this.selects[i].options );
          this.elementVisible[i] = true;
          this.xvalue = [];
          if ( select.selectedIndex != null && select.selectedIndex != undefined && select.selectedIndex >= 0 ) {
            this.value = select.options[select.selectedIndex].value;
          }  // if
          
          this.xvalue.push( this.value );
        } else { 
          select = this.clearSelect();
        } // if
      
        if ( vAlign || this.width > 0 ) {
          var pxLen = this.width > 0 ? this.width : letters2px( maxOptionLen ) + 40;
          select.style.width = pxLen + 'px';
        } // if
      
        if ( this.name ) select.setAttribute( 'name', this.name );
        select.setAttribute( 'ind', i );
      
        var self = this;
        select.onchange = function() {
          var ind = Number( this.getAttribute( 'ind' ) );
          self.selected( ind, this.value );
          self.onchange( this.options[this.selectedIndex].value, this, this.options[this.selectedIndex].additionFields );
        } // select.onchange

        this.selectElements.push( select );
      
        if ( i == 0 || vAlign ) {
          markupTR = cr( 'TR' );
          markupTableBody.appendChild( markupTR );
        } // if
        
        if ( hasTitle && ( i == 0 || ( this.titles && this.titles.length > i ) ) ) {
          title = this.titles ? this.titles[i] : this.title;
        } else {
          title = ( this.treeAlign == TREE_V_ALIGN ? '&nbsp;' : '' );
        } // if

        titleTD = cr( 'TD' );
        markupTR.appendChild( titleTD );
        titleTD.className = 'treeSelect_title';
        titleTD.innerHTML = title;
      
        markupTD = cr( 'TD' );
        markupTR.appendChild( markupTD );
        markupTD.appendChild( select );
      
        select.markupElement = vAlign ? markupTR : markupTD;
      
        if ( i != 0 ) this.hideSelectElement( select );
      } // for
    
    var i = 0;
    while ( this.value && this.selected( i++, this.value ) );

    return markupTable;
    } catch( error ) {
      jsLog( error, 'itools/elements/treeSelect.js', 'TreeSelect.markup' );
    } // try
  }, // markup
  
  update: function( selects ) {
    if ( !selects ) return;
    this.selects = selects;
    for ( var i = 0; i < this.selectElements.length; i++ ) {
      var select = this.selectElements[i];
      this.clearSelect( select );
    } // if
    this.fillSelect( this.selectElements[0], this.selects[0].options );
  },
  
	fillTree: function( value ) {
	  if ( !value ) return;
    if ( value.constructor == Array ) {
      values = $A( value ).collect( function( el ){ return parseInt( el );});
    } else {
		var searchValue = parseInt( value );
  		var values = [value];
  		
      for ( var i = this.selects.length - 1; i > 0; i-- ) {
  		  var select = this.selects[i];
  		  var flag = true;
  			for ( var j = 0; j < select.options.length; j++ ) {
  			  var key = parseInt( select.options[j].key );
  				if ( key  ==  searchValue  ) {
  					flag = false;
  					searchValue = parseInt( select.options[j].parent );
  				} // if
  			} // for
  			if ( flag ) return;
  			values.unshift( searchValue )
  		} // for	
  	} // if	
    var xvalue = [];
    var realValue;
    
    for ( var i=0; i < this.selectElements.length; i++ ) {
      var select = this.selectElements[i];
      var noSelectedFlag = true;
      for ( var j=0; j < select.options.length; j++ ) {
        var option = select.options[j];
			  
        if ( parseInt( option.value ) == values[i] ) {
           option.selected = true;
           noSelectedFlag  = false;
        } // if   
      } // for
      if ( noSelectedFlag ) break;
      this.selected( i, values[i] );
			this.showSelectElement( select );
      realValue = values[i];
      xvalue.push( values[i] );
		} // for
//		this.value  = value;
//		this.xvalue = values;
    this.value  = realValue;
    this.xvalue = xvalue;
    return values;
	}, // fillTree
	
  clearSelect: function( selectElement ) {
    if ( !selectElement )	selectElement = cr( 'SELECT' );
		if ( this.size ) selectElement.size = this.size;
    removeChildren( selectElement );
	
    if ( this.emptyOption ) {
      selectElement.options[0] = new Option( this.emptyOption, '0' );
    } // if
	
    return selectElement;
  },
  
  selected: function( selectInd, selectValue ) {
    var nextSelectInd = selectInd+1;
    var nextSelect = this.selects[nextSelectInd];
    
    if ( nextSelect ) {
      var options = nextSelect.options;
      var nextOptions = options.findAll( function( item ) { return item.parent == selectValue } );
      
      if ( nextOptions && nextOptions.length > 0 ) {
        var nextSelectElement = this.selectElements[nextSelectInd];
        this.fillSelect( nextSelectElement, nextOptions );
        this.showSelectElement( nextSelectElement );
        this.value = nextSelectElement.options[nextSelectElement.selectedIndex].value;
      } else {
        this.hideSelectElements( selectInd );
        nextSelectInd--;
      } // if
    }// if
    
    this.xvalue = [];
    for ( var i=0; i <= nextSelectInd; i++ ) {
      var select = this.selectElements[i];
      if ( !select ) break;
      var value = select.options[select.selectedIndex].value;
      this.xvalue.push( value );
      /*if ( parseInt( value ) != 0 || i == 0 )*/ this.value = value;
    } // for
    if( nextSelect ) return true;
    else return false;
  }, // selected
  
  fillSelect: function( select, options ) {
    var selectElement = this.clearSelect( select );
  
    var k = this.emptyOption ? 1 : 0;
    if( this.autoChoise && options.length == 1 ) { // если нужно выбрать авто значение при одной опции пустую опцию не добавлять
      k = 0;
    }; // if
    for ( var j=0; j < options.length; j++ ) {
      selectElement.options[j+k] = new Option( options[j].value, options[j].key );
      selectElement.options[j+k].additionFields = options[j].additionFields;
    } // for
    if( this.autoChoise && options.length == 1 ) {
      var firstOption = $A( selectElement.options ).first();
      firstOption.selected = true;
      this.value = parseInt( firstOption.value );
      this.xvalue[ parseInt( selectElement.ind ) ] = parseInt( firstOption.value );
      this.onchange( firstOption.value, selectElement, firstOption.additionFields );
    }; // if
    return selectElement;
  },
  
  hideSelectElements: function( afterInd ) {
    var visList = this.elementVisible;
  
    for ( var i=afterInd+1; i < visList.length; i++ ) {
      var select = this.selectElements[i];
      this.hideSelectElement( select );
    } // for
  }, // hideSelectElements
  
  hideSelectElement: function( select ) {
    if ( select ) {
      hideElement( select.markupElement );
      
      var ind = Number( select.getAttribute( 'ind' ) );
      this.elementVisible[ind] = false;
    } // if   
  }, // hideSelectElement
  
  showSelectElement: function( select ) {
    if ( select ) {
      displayElement( select.markupElement );
      
      var ind = Number( select.getAttribute( 'ind' ) );
      this.elementVisible[ind] = true;
    } // if   
  } // showSelectElement
});

TreeSelectXML = Class.create({
  initialize: function( xmlDocument ) {
    this.xmlDoc = xmlDocument;
  }, // initialize
  
  parse: function() {
    var xml      = this.xmlDoc;
    var root     = xml.nodeType == 9 ? xml : xml.documentElement;
    var selects  = root.getElementsByTagName( 'select' );
    var res      = [];
    
    for ( var i = 0; i < selects.length; i++ ) {
      var options = selects[i].getElementsByTagName( 'option' );
      var select = $H();
          
      select.options = [];
      
      for ( var j = 0; j < options.length; j++ ) {
        var option = options[j];
        additionFieldsValue = {};
        var optionObj = {
          key         : option.getAttribute( 'value' ),
          value       : option.firstChild.nodeValue,
          parent      : option.getAttribute( 'parent' ),
          additionFields : additionFieldsValue,
          hasChildren : option.getAttribute( 'has_children' )
        }
        select.options.push( optionObj );
      } // for
            
      res.push( select );
    } // for
    
    return res;
  } // parse
}); // TreeSelectXML