SelectMenu.prototype.id = null;
SelectMenu.prototype.header = null;
SelectMenu.prototype.headerText = null;
SelectMenu.prototype.menu = null;
SelectMenu.prototype.parentNode = null;
SelectMenu.prototype.isOpen = false;
SelectMenu.prototype.isVisible = false;
SelectMenu.prototype.selecteNode = null;
SelectMenu.prototype.initialHeader = "";
SelectMenu.prototype.index = 1;
SelectMenu.prototype.hasBeenOpened = false;
SelectMenu.prototype.zero = false;
SelectMenu.prototype.nosort = null;

SelectMenu.prototype.currentNode = null;
SelectMenu.prototype.currentNodeIndex = 0;

SelectMenu.prototype.headerClass = null;
SelectMenu.prototype.itemClass = null;

//Default border options
SelectMenu.prototype.innerBorder = true;
SelectMenu.prototype.borderWidth = 1;
SelectMenu.prototype.borderColor = "black";

//Default menu item options
SelectMenu.prototype.itemBackground = "lightgray";
SelectMenu.prototype.itemTextColor = "blue";

//Default dimentions
SelectMenu.prototype.menuItemHeight = 15;
SelectMenu.prototype.menuWidth = 200;
SelectMenu.prototype.headerWidth = 200;
SelectMenu.prototype.headerHeight = 15;

//Default menu location
SelectMenu.prototype.x = 20;
SelectMenu.prototype.y = 30;

SelectMenu.prototype.nodeText = null;

SelectMenu.prototype.menuEvents = null;
SelectMenu.prototype.nodeEvents = null;
SelectMenu.prototype.nodes = null;
SelectMenu.prototype.parent = null;

//Event handlers
SelectMenu.prototype.onclick = null;
SelectMenu.prototype.onmousedown = null;
SelectMenu.prototype.onmouseup = null;
SelectMenu.prototype.onmouseover = null;
SelectMenu.prototype.onmouseout = null;

SelectMenu.prototype.initMenu = function(){
  this.setHeaderSize(this.headerHeight, this.headerWidth);
  this.setMenuItemHeight(this.menuItemHeight);
  this.setMenuWidth(this.menuWidth);
  this.moveMenuTo(this.x, this.y);
  this.showInnerBorder(this.innerBorder);
  this.setBorderWidth(this.borderWidth);
  this.setBorderColor(this.borderColor);
  this.zIndex(this.index);
  this.setItemBackground(this.itemBackground);
  this.setItemTextColor(this.itemTextColor);
  if (this.nodes.length > 1 && !this.nosort) this.nodes.sort(compareByNodeText);
  this.buildMenu();
  this.hasBeenOpened = true;
}

SelectMenu.prototype.buildMenu = function() {
  //Set the background color of the menu.
  this.menu.cbe.background(this.borderColor);
  //Set the size of the background based on the number of nodes.
  if (this.showInnerBorder()) {
    this.menu.cbe.resizeTo(this.menuWidth, ((this.nodes.length)*this.menuItemHeight)+((this.nodes.length+1)*this.borderWidth));
  } else {
    this.menu.cbe.resizeTo(this.menuWidth, ((this.nodes.length)*this.menuItemHeight)+(2*this.borderWidth));
  }

  //Reset the index of the node, resize and move to it's proper location in the menu.
  var i = 0;
  for (i=0; i<this.nodes.length; i++) {
    var node = this.nodes[i];
    node.index = i;
    node.appendNode(this.itemClass);
    node.element.cbe.resizeTo(this.menuWidth-(2*this.borderWidth), this.menuItemHeight);
    if (is.gecko || (is.ie && is.mac)) node.element.style.paddingTop = "2px";
    node.element.cbe.background(this.itemBackground);
    node.element.cbe.color(this.itemTextColor);

    if (this.showInnerBorder()) {
      node.element.cbe.moveTo(this.borderWidth,
                              ((node.index)*this.menuItemHeight)+((node.index+1)*this.borderWidth));
    } else {
      node.element.cbe.moveTo(this.borderWidth,
                              ((node.index)*this.menuItemHeight)+this.borderWidth);
    }
    node.element.cbe.show();
    if (node.hasChildMenu()) {
      node.childMenu.initMenu();
      if (this.showInnerBorder()) {
        if(is.ie){
          node.childMenu.menu.cbe.moveBy(this.menuWidth-4, (this.menuItemHeight*i)+((node.index+1)*this.borderWidth)+4);
        }
        else {
          node.childMenu.menu.cbe.moveBy(this.menuWidth-2, (this.menuItemHeight*i)+((node.index+1)*this.borderWidth)+6);
        }
      } else {
        if(is.ie){
          node.childMenu.menu.cbe.moveBy(this.menuWidth-4, this.menuItemHeight*i+4);
        }
        else {
          node.childMenu.menu.cbe.moveBy(this.menuWidth-2, this.menuItemHeight*i+6);
        }
      }
    }
  }
}

/**
 * Add a node to the menu.
 */
SelectMenu.prototype.addNode = function(text, menu) {
  if (is.nav4) {
    words = text.split(' ');
    text = '';
    for (i=0; i<words.length; i++) {
      text = text + words[i] + '&nbsp;';
    }
  }

  //If a node with that same text is already there then
  //return that node.
  for (i=0; i<this.nodes.length; i++) {
    var node = this.nodes[i];
    if ( node.text == text ) {
      return node;
    }
  }

  //If the node is not there then make a new one.
  var node = new MenuNode(this.id + "." + (this.nodes.length+1), this);
  if (menu) {
    node.setChildMenu(menu);
    menu.parentNode = node;
  }
  node.text = text;
  this.nodes[this.nodes.length] = node;

  return node;
}

/**
 * Sets an event for the menu header.
 */
SelectMenu.prototype.addMenuEvent = function(event, eventListener) {
  this.header.cbe.addEventListener(event, eventListener);
  var index;
  if (!this.nodeEvents.length) index = 0;
  else index = this.menuEvents.length;
  this.menuEvents[index] = new Array();
  this.menuEvents[index][0] = event;
  this.menuEvents[index][1] = eventListener;
}

/**
 * Sets and event for each menu item.
 */
SelectMenu.prototype.addMenuItemEvent = function(event, eventListener) {
  var index;
  if (!this.nodeEvents.length) index = 0;
  else index = this.nodeEvents.length;
  this.nodeEvents[index] = new Array();
  this.nodeEvents[index][0] = event;
  this.nodeEvents[index][1] = eventListener;
}

/**
 * Sets the initial text that will be displayed in the selection box.
 */
SelectMenu.prototype.setInitialHeader = function(header){
  this.initialHeader = header;
  this.setHeader(header);
}

/**
 * Sets the text that will be displayed in the selection box.
 */
SelectMenu.prototype.setHeader = function(header) {
  if (is.nav4 && is.mac) {
    this.header.cbe.innerHtml('<font point-size="9" color="'+this.itemTextColor+'" face="arial,verdana,sans-serif" style="padding-top:1px;"><b>&nbsp;' + header + '<b></font>');
  } else if (is.nav4) {
    this.header.cbe.innerHtml('<font point-size="7" color="'+this.itemTextColor+'" face="arial,verdana,sans-serif" style="padding-top:1px;"><b>&nbsp;' + header + '<b></font>');
  } else {
    this.header.cbe.innerHtml('<div class="'+this.headerClass+'" style="margin-left:2px;margin-top:2px;">' + header + '</div>');
  }
  this.headerText = header;
}

/**
 * Sets the style for the menu items.
 */
SelectMenu.prototype.setMenuItemClass = function(style){
  this.itemClass = style;
}

/**
 * Sets the class for the header.
 */
SelectMenu.prototype.setHeaderClass = function(style){
  this.headerClass = style;
  this.setHeader(this.initialHeader);
}

/**
 * Set the height and with of the menu header.
 */
SelectMenu.prototype.setHeaderSize = function(height, width){
  this.headerHeight = height;
  this.headerWidth = width;
  this.header.cbe.resizeTo(this.headerWidth, this.headerHeight);

  //Make shure the menu item openens flush with the left bottom corner.
  this.menu.cbe.moveTo(this.x, (this.y+this.headerHeight));
}

/**
 * Moves the menu to the x y coordinates.
 */
SelectMenu.prototype.moveMenuTo = function(x, y){
  this.header.cbe.moveTo(x, y);
  this.menu.cbe.moveTo(x, (y+this.headerHeight));
  this.x = x;
  this.y = y;
}

/**
 * Set the height of an individual menu item. Needs to be called
 * before the menu is opened.
 */
SelectMenu.prototype.setMenuItemHeight = function(height){
  this.menuItemHeight = height;
  this.hasBeenOpend = false;
}

/**
 * Set the width of the menu. Needs to be called before the menu is opened.
 */
SelectMenu.prototype.setMenuWidth = function(width){
  this.menuWidth = width;
  this.hasBeenOpend = false;
}

/**
 * true if the inner borders should be shown.
 */
SelectMenu.prototype.showInnerBorder = function(show) {
  if (show == null) return this.innerBorder;
  else {
    this.innerBorder = show;
    this.hasBeenOpend = false;
  }
}

/**
 * Set the width of the border.
 */
SelectMenu.prototype.setBorderWidth = function(width) {
  this.borderWidth = width;
  this.hasBeenOpend = false;
}

/**
 * Set the border color.
 */
SelectMenu.prototype.setBorderColor = function(color) {
  this.borderColor = color;
  this.menu.cbe.background(this.borderColor);
}

/**
 * Set the zIndex of this menu.
 */
SelectMenu.prototype.zIndex = function(index) {
  this.header.cbe.zIndex(index);
  this.menu.cbe.zIndex(index);
  this.index = index;
}

/**
 * Set the background color of a menu item.
 */
SelectMenu.prototype.setItemBackground = function(color) {
  this.itemBackground = color;
  this.hasBeenOpened = false;
}

/**
 * Set the background color of a menu item.
 */
SelectMenu.prototype.setItemTextColor = function(color) {
  this.itemTextColor = color;
  this.header.cbe.color(this.itemTextColor);
  this.hasBeenOpened = false;
}



/**
 * Return the parent node for this menu. null if one does not exist.
 */
SelectMenu.prototype.getParent = function() {
  return this.parent;
}

/**
 * Open the menu items with no spcial effect.
 */
SelectMenu.prototype.slideOpen = function(speed) {
  if (!this.isOpen) {
    if (!speed) {
      speed = 300;
    }
    if (!this.hasBeenOpen) {
      this.initMenu();
      for (i=0;i<this.nodes.length;i++) {
        this.nodes[i].element.cbe.resizeTo(this.menuWidth-(2*this.borderWidth), this.menuItemHeight);
        this.nodes[i].element.cbe.moveTo(this.borderWidth,this.borderWidth);
        this.nodes[i].element.cbe.background(this.itemBackground);
        this.nodes[i].element.cbe.color(this.itemTextColor);
      }
    }

    with (this.menu.cbe) {
      background('transparent');
      if (this.showInnerBorder()) {
        resizeTo(this.menuWidth, (this.nodes.length*this.menuItemHeight)+((this.nodes.length+1)*this.borderWidth));
      } else {
        resizeTo(this.menuWidth, (this.nodes.length*this.menuItemHeight)+(2*this.borderWidth));
      }
    }

    this.menu.cbe.show();

    //Slide in each item at the same rate.
    for (i=0;i<this.nodes.length-1;i++) {
      if (this.showInnerBorder()) {
        this.nodes[i].element.cbe.slideTo(this.borderWidth,
                                          ((i)*this.menuItemHeight)+((i+1)*this.borderWidth), speed);
      } else {
        this.nodes[i].element.cbe.slideTo(this.borderWidth,
                                          ((i)*this.menuItemHeight) + this.borderWidth, speed);
      }
    }
    if (this.showInnerBorder()) {
      this.nodes[this.nodes.length-1].element.cbe.slideTo(this.borderWidth,
                                                          ((this.nodes.length-1)*this.menuItemHeight)+(this.nodes.length*this.borderWidth),
                                                          speed,
                                                          "window.cbeAll["+this.menu.cbe.index+"].background('"+this.borderColor+"')");
    } else {
      this.nodes[this.nodes.length-1].element.cbe.slideTo(this.borderWidth,
                                                          ((this.nodes.length-1)*this.menuItemHeight)+this.borderWidth,
                                                          speed,
                                                          "window.cbeAll["+this.menu.cbe.index+"].background('"+this.borderColor+"')");
    }
    this.isOpen=true;
    this.zero=true;
  }
}

/**
 * Open the menu like it is animated.
 */
SelectMenu.prototype.animateOpen = function(d) {
  if (is.safari) {
    this.open();
    return;
  }
  if (!this.isOpen) {
    this.menu.cbe.show();
    if (!(is.ie5 && is.mac)) {
      var rate = (3*Math.floor(this.nodes.length/3))+3;
      if (d=='s' || d=='n') {
        this.menu.cbe.autoClip(d, 'unclip', rate);
      } else {
        this.menu.cbe.autoClip(d, 'unclip', 20);
      }
    }
    this.isOpen=true;
  }
}

SelectMenu.prototype.fadeOpen = function() {
  if (!this.isOpen) {
    this.menu.cbe.fadeIn();
    this.isOpen=true;
  }
}

SelectMenu.prototype.open = function() {
  if (!this.isOpen) {
    this.menu.cbe.show();
    this.isOpen=true;
  }
}

SelectMenu.prototype.fadeInMenu = function() {
  if (!this.isVisible) {
    this.setInitialHeader(this.initialHeader);
    this.header.cbe.fadeIn();
    this.isVisible=true;
  }
}

SelectMenu.prototype.show = function() {
  //Maybe the menu should remember it's value and maybe one day it will.
  //But for now it resets.
  if (!this.isVisible) {
    this.header.cbe.show();
    this.isVisible=true;
  }
}

/**
 * Hide the menu.
 */
SelectMenu.prototype.hide = function() {
  this.close();
  this.isVisible = false;
  this.header.cbe.hide();
}

/**
 * Hide the menu items.
 */
SelectMenu.prototype.close = function() {
  this.isOpen = false;
  if (this.currentNodeIndex != null && this.nodes[this.currentNodeIndex] && this.nodes[this.currentNodeIndex].hasChildMenu()) {
    this.nodes[this.currentNodeIndex].element.cbe.color("#4E8893");
    this.nodes[this.currentNodeIndex].childMenu.close();
    this.nodes[this.currentNodeIndex].menuArrow.src = cbeGetPreloadedImageByName('childMenuArrowOff').src;
  }
  this.menu.cbe.hide();
  if (this.zero) {
    for (i=0;i<this.nodes.length;i++) {
      this.nodes[i].element.cbe.moveTo(this.borderWidth,this.borderWidth);
    }
  }
}

/**
 * Constructor
 */
function SelectMenu(id, nosort) {
  this.nosort = nosort;
  this.nodeText = new Array();
  this.nodes = new Array();
  this.nodeEvents = new Array();
  this.menuEvents = new Array();
  if (id == null) {
    alert('A menu must have an id');
    return;
  }
  this.id = id;
  this.menu = cbeGetElementById(id);
  this.header = document.cbe.createElement('div');
  //This aint generic.
  this.header.className = "cbeLayer";
  this.menu.cbe.parentNode.appendChild(this.header);
  this.header.cbe.hide();
}
