var model;
var menu;

////////////////////////////////////////////////////////////////////////////////
// MODEL

function ChildNodesM() {
  this.childs = new Array();

  this.addChild = function(node) {
    this.childs[this.childs.length] = node;
  }

  this.size = function() {
    return this.childs.length;
  }

  this.get = function(idx) {
    return this.childs[idx];
  }

  this.toString = function() {
    for (var i = 0; i < this.childs.length; i++) {
      this.childs[i].toString();
    }
  }
}

function NodeM(parent, id, name, href ,level) {
  this.parent = parent;
  this.id = id;
  this.name = name;
  this.href = href;
  this.level = level;
  this.selectedMenu = false;
  this.expanded = false;
  this.childs = new ChildNodesM();

  this.addChild = function(node) {
    this.childs.addChild(node);
  }

  this.hasChilds = function() {
    return this.childs.size() > 0;
  }

  this.size = function() {
    return this.childs.size();
  }

  this.getNode = function(idx) {
    return this.childs.get(idx);
  }

  this.expand = function() {
    this.expanded = true;
    menu.onExpandNode(this);

    if (this.parent != null)
      this.parent.expand();
  }

  this.collapse = function() {
    this.expanded = false;
    menu.onCollapseNode(this);

    for (var i = 0; i < this.childs.length; i++) {
      this.childs.get(i).collapse();
    }
  }

  this.selectNode = function(id) {
    for (var i = 0; i < this.childs.size(); i++) {
      var node = this.childs.get(i);
      if (node.id == id) {
        node.selectedMenu = true;
      } else {
        node.selectedMenu = false;
      }
      node.selectNode(id);
    }
  }
}

function MenuM() {
  this.childs = new ChildNodesM();
  this.nodes = [];

  this.addNode = function(parentId, id, name, href) {
    var level;
    var parent = null;
    if (parentId != null) {
      parent = this.nodes[parentId];
    }
    if (parent != null) {
      level = parent.level + 1;
    } else {
      parent = this;
      level = 0;
    }
    var node = new NodeM(this == parent ? null : parent, id, name, href, level);
    parent.addChild(node);
    this.nodes[id] = node;
  }

  this.addChild = function(node) {
    this.childs.addChild(node);
  }

  this.getNode = function(idx) {
    return this.childs.get(idx);
  }

  this.getNodeById = function(id) {
    return this.nodes[id];
  }

  this.size = function() {
    return this.childs.size();
  }

  this.expand = function(id) {
    var node = this.nodes[id];
    if (node != null)
      node.expand();
  }

  this.selectNode = function(id) {
    for (var i = 0; i < this.childs.size(); i++) {
      var node = this.childs.get(i);
      if (node.id == id) {
        node.selectedMenu = true;
      } else {
        node.selectedMenu = false;
      }
      node.selectNode(id);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
// VIEW

function MenuV(html) {
  this.html = html;

  this.createImg = function() {
    var img = document.createElement("IMG");
    img.align = "top";
    img.style.width = "7px";
    img.style.height = "7px";

    return img;
  }

  this.getImgEmpty = function() {
    var img = this.createImg();
    img.src = "/images/e.gif";
    img.alt = " ";

    return img;
  }

  this.getImgPlus = function() {
    var img = this.createImg();
    img.src = "/images/_plus.gif";
    img.alt = "+";
    addEvent(img, "mouseup", onexpand);

    return img;
  }

  this.getImgMinus = function() {
    var img = this.createImg();
    img.src = "/images/_minus.gif";
    img.alt = "-";
    addEvent(img, "mouseup", onexpand);

    return img;
  }

  this.getImgDivLevel1 = function(node) {
    if (node.hasChilds()) {
      if (node.expanded)
        return this.getImgMinus();
      else {
        return this.getImgPlus();
      }
    } else
      return this.getImgEmpty();
  }

  this.getDivLevel1 = function(node) {
    var div = document.createElement("DIV");
    div.className = "menu_level1";
    div.id = "div" + node.id;

    var table = document.createElement("TABLE");
    div.appendChild(table);
    var row = table.insertRow(0);
    var cell = row.insertCell(0);
    cell.appendChild(this.getImgDivLevel1(node));

    var a = document.createElement("A");
    a.href = node.href;
    a.className = node.selectedMenu ? "menu_selected" : "";
    a.appendChild(document.createTextNode(node.name));
    cell = row.insertCell(1);
    cell.appendChild(a);

    return div;
  }

  this.getDivLevel2 = function(node) {
    var outerDiv = document.createElement("DIV");
    outerDiv.className = "menu_level2_div";
    for (var i = 0; i < node.size(); i++) {
      var child = node.getNode(i);
      var div = document.createElement("DIV");
      div.className = "menu_level2";
      div.id = "div" + child.id;
      var a = document.createElement("A");
      a.href = child.href;
      a.className = child.selectedMenu ? "menu_selected" : "";
      a.appendChild(document.createTextNode(child.name));
      div.appendChild(a);
      outerDiv.appendChild(div);
    }

    return outerDiv;
  }

  this.showLevel2 = function(node, parent) {
    if (node.hasChilds()) {
      var outerDiv = this.getDivLevel2(node);
      parent.appendChild(outerDiv);
    }
  }

  this.showMenu = function() {
    // Удаляем потомков
    removeChildrenRecursively(this.html);
//    for(var i = 0; i < this.html.childNodes.length; i++) {
//      this.html.removeChild(this.html.childNodes[i]);
//    }

    // Создаём меню
    for (var i = 0; i < model.size(); i++) {
      var child = model.getNode(i);
      var div = this.getDivLevel1(child);
      this.html.appendChild(div);

      if (child.expanded)
        this.showLevel2(child, this.html);
    }
  }

  this.onExpandNode = function(node) {
    if (!node.hasChilds())
      return;

    var divNode = document.getElementById("div" + node.id);
    var divParent = divNode.parentNode;
    var childs = new Array();
    var skipNext = false;
    var idx = 0;

    for (var i = 0; i < divParent.childNodes.length; i++) {
      var child = divParent.childNodes[i];
      if (child == divNode) {
        var divNew = this.getDivLevel1(node);
        divParent.replaceChild(divNew, divNode);
        childs[idx] = divNew;
        idx++;
        childs[idx] = this.getDivLevel2(node);
        idx++;
      } else {
        childs[idx] = child;
        idx++;
      }
    }

    for (var i = 0; i < childs.length; i++) {
      divParent.appendChild(childs[i]);
    }
  }

  this.onCollapseNode = function(node) {
    if (!node.hasChilds())
      return;

    var divNode = document.getElementById("div" + node.id);
    var divParent = divNode.parentNode;
    var childs = new Array();
    var skipNext = false;

    for (var i = 0; i < divParent.childNodes.length; ) {
      var child = divParent.childNodes[i];
      if (child == divNode) {
        var divNew = this.getDivLevel1(node);
        divParent.replaceChild(divNew, divNode);
        childs[i] = divNew;
        i++;
        skipNext = true;
      } else if (!skipNext) {
        childs[i] = child;
        i++;
      } else {
        divParent.removeChild(child);
        skipNext = false;
      }
    }

    for (var i = 0; i < childs.length; i++) {
      divParent.appendChild(childs[i]);
    }
  }

  this.showMenu();
}

function onexpand(e) {
  // Элемент по которому кликнули мышкой
  var el = window.event ? window.event.srcElement : e.currentTarget;
  // Ищем пункт мену, которому он соответствует
  while (el != null && el.tagName != "DIV") {
    el = el.parentNode;
  }
  if (el == null)
    return;

  var strId = new String(el.id);
  if (strId.search("div") == 0) {
    var menuNodeId = strId.substr(3);
    var menuNode = model.getNodeById(menuNodeId);
    if (menuNode != null) {
      if (menuNode.expanded)
        menuNode.collapse();
      else
        menuNode.expand();
    }
  }
}

function addEvent(el, eventName, func) {
/*	if (el.addEventListener) { // Gecko / W3C
		el.addEventListener(eventName, func);
  } else */if (el.attachEvent) { // IE
    el.attachEvent("on" + eventName, func);
	} else { // Opera (or old browsers)
		el["on" + eventName] = func;
	}
}

function removeChildrenRecursively(node) {
  if (!node)
    return;
  while (node.hasChildNodes()) {
    removeChildrenRecursively(node.firstChild);
    node.removeChild(node.firstChild);
  }
}

model = new MenuM();

