/******************************************************************************
 * Copyright (c) 2002,2003 Peter 'Merlin' Balsiger and Fredy 'Mythos' Dobler
 * All rights reserved
 *
 * This file is part of Dungeon Master Assistant.
 *
 * Dungeon Master Assistant 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.
 *
 * Dungeon Master Assistant 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 Dungeon Master Assistant; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *****************************************************************************/

//------------------------------------------------------------------- header

/**
 * This is the main DMA javascript file. It contains most javascript methods
 * used in all the HTML pages.
 * 
 * @file          DMA.js
 * 
 * @author        Peter Balsiger
 *
 */

//..........................................................................

//__________________________________________________________________________

//---------------------------------------------------------------- variables

/** The login window, if any. */
var loginWindow = null;

//..........................................................................

//---------------------------------- save ----------------------------------

/**
 * Save all the currently set values.
 *
 * @param inStorage the specification for the storage
 *
 */
function save(inStorage, inType)
{
  // remove the move away code
  window.onbeforeunload = undefined;

  var values = { };
  values._data = inStorage;
  values._type = inType;
  
  for(var i = 0, editable; editable = gui.Editable.all[i]; i++)
  {
    var id    = editable.id;    
    var value;

    if(editable.isDefined())
      value = editable.getValue();
    else
      value = "$undefined$";
    
    if(value.length > 0)
      values[id + "::" + editable.key] = value;
  }

  // send the data to the server
  var result = ajax("/actions/save", values, 
                    function(inResult) { eval(inResult); });
}

//..........................................................................
//------------------------------- saveEntry --------------------------------

/** Save all the currently set values.
 *
 * @param inID the id of the entry to save
 *
 */
function saveEntry(inID)
{
  gui.values = {};
  gui.values._id = inID;
  
  for(var i = 0, editable; editable = gui.Editable.all[i]; i++)
    if(!editable.key.match(/.*\-.*/))
    {
      var value = editable.getValue();

      if(value.length > 0)
        gui.values[editable.key] = editable.getValue();
    }

  for(var i = 0, editable; editable = gui.Editable.all[i]; i++)
  {
    var parts = editable.key.match(/(.*)\-(.*)/);
    
    if(parts)
    {
      var value = editable.getValue();

      if(value && value.length > 0)
        gui.values[parts[1]] += parts[2] + editable.getValue();        
    }
  }

  // send the data to the server
  var result = ajax("/actions/save-entry", gui.values, 
                    function(inResult) { eval(inResult); });

  // remove the move away code
  window.onbeforeunload = undefined;
}

//..........................................................................
//------------------------------- saveIndex --------------------------------

/** Save all the currently set values.
 *
 * @param inID the id of the entry to save
 *
 */
function saveIndex(inID, inIndex)
{
  gui.values = {};
  gui.values._id = inID;
  gui.values._index = inIndex;
  
  for(var i = 0, editable; editable = gui.Editable.all[i]; i++)
    if(!editable.key.match(/.*\-.*/))
    {
      var value = editable.getValue();

      if(value.length > 0)
        gui.values[editable.key] = editable.getValue();
    }

  for(var i = 0, editable; editable = gui.Editable.all[i]; i++)
  {
    var parts = editable.key.match(/(.*)\-(.*)/);
    
    if(parts)
      gui.values[parts[1]] += parts[2] + editable.getValue();
  }

  // remove the move away code
  window.onbeforeunload = undefined;

  // sent the data to the server
  eval(ajax("/actions/save-index", gui.values));
}

//..........................................................................
//--------------------------------- login ----------------------------------

/**
  *
  * Create the login dialog and ask the user to log in.
  *
  * @param inElement the element to attach the login window to.
  *
  */
function login(inElement)
{
  inElement.nextSibling.style.display = 'block';
  inElement.nextSibling.firstChild.username.focus();
}

//..........................................................................
//--------------------------------- logout ---------------------------------

/**
  *
  * Logout the user.
  *
  */
function logout()
{
  var result = ajax("/actions/logout");

  gui.reload(); 
}

//..........................................................................
//-------------------------------- doLogin ---------------------------------

/**
  *
  * Try to login into the server. If the login is successful, the page is
  * reloaded, otherwise an error message will be shown.
  *
  * @param       inUsername the username
  * @param       inPassword the password 
  *
  */
function doLogin(inUsername, inPassword)
{
  var result = 
    ajax("/actions/login", { username: inUsername, password: inPassword });

  if(result != "")
    // show the error
    document.getElementById('error-login').innerHTML = result;
  else
    // reload the page to show login
    gui.reload();

  return false;
}

//..........................................................................
//---------------------------------- mail ----------------------------------

/**
 * Mail some content to a user. This will ask for a confirmation of the user.
 * 
 * @param       inAction  the action to take for really sending the mail
 * @param       inAccount the name of the account to use for sending
 * @param       inEmail   the email address to use for sending out mail.
 * @param       inSubject the standard subject to be mailed
 * @param       inText    the standard text of the mail
 *
 */
function mail(inEmail, inSubject, inText, inValues)
{
  var values = "";
  for(var key in inValues) 
    values += ", " + key + ": \"" + inValues[key] + "\"";

  var contents = 
    "<form class='mail' onsubmit='eval(ajax(\"/actions/mail\", {" 
    + "subject: this.subject.value, text: this.text.value" + values 
    + "})); return false;'>"
    + "<label>Subject:</label>"
    + "<input value='" + inSubject + "' size='50' name='subject'>"
    + "<label>Message:</label>"
    + "<textarea name='text' cols='50' rows='20'>" 
    + inText.replace(/\\n/g, "\n")
    + "</textarea>"
    + "<div style='text-align:right'>"
    + "<button onclick='gui.removeWindow(\"mail\"); return false'>"
    + "Cancel"
    + "</button>"
    + "<button>Send</button>"
    + "</div>"
    + "</form>";

  gui.showWindow("mail", "mail", "Send Mail", contents);
}

//..........................................................................

//----- setupTreeTable -----------------------------------------------------

/**
 * Setup a tree table with drag and drop functionality.
 *
 * @param inID the id of the complete table
 * @param inEntry the class used for entries
 * @param inContainer the class used for containers
 */
function setupTreeTable(inID, inEntry, inContainer) 
{
  $j(document).ready(function() 
  {
    // setup the tree table
    $j('#' + inID).treeTable({
      initialState: 'collapsed',
      clickableNodeNames: true
    });
        
    // make entries and containers draggable
    $j('#' + inID + ' .' + inEntry + ', #' + inID + ' .' + inContainer).
      draggable(
    {
      helper: function(inEvent) {
        var dragged = $j(this).find('.item-name').clone()[0];
        dragged.className = 'item-dragged';
        return dragged;
      },
      opacity: .75,
      refreshPositions: true, // Performance?
      revert: 'invalid',
      revertDuration: 300,
      scroll: true,
      delay: 100
    });
      
    $j('#' + inID + ' .' + inEntry + ', #' + inID + ' .' + inContainer).
      droppable(
    {
      accept: '.' + inEntry + ', .' + inContainer,
      drop: function(e, ui) 
      {
        ui.draggable.appendBranchTo(this, $j(this).hasClass(inEntry));
        
        var names = this.className.split(' ');
    
        var containerID;
        for(var i = 0; i < names.length; i++) 
          if(names[i].match("child-of-")) 
            containerID = names[i].substring(14);

        // send the message to the server (we have to deal with the target here,
        // because a Container can call this as well)
        eval(ajax("/actions/move", 
                  { 
                    id: ui.draggable[0].id.substring(5), 
                    target: containerID, 
                    sibling: this.id.substring(5) 
                  }, 
                  null));
      },
      hoverClass: 'accept',
      over: function(e, ui) 
      {
        var node = $j(this);

        // Make the droppable branch expand when a draggable node is
        // moved over it.
        if(node.hasClass(inContainer) && this.id != ui.draggable.id 
           && !node.is('.expanded')) 
          node.expand();
      }
    });

    $j('#' + inID + ' .' + inEntry + ', #' + inID + ' .' + inContainer).
      click(function(e) 
            {
              // don't do this for the first entry
              if($j(this).prev().length > 0)
                $j('#item-desc').html(ajax("/entry/item/" 
                                           + this.id.substring(5) 
                                           + "?body&short", null, null));
            });

    // Make visible that a row is clicked
    $j('table#' + inID + ' tbody tr').mousedown(function() 
    {
      // Deselect currently selected rows
      $j('tr.selected').removeClass('selected');

      $j(this).addClass('selected');
    });
        
    // Make sure row is selected when span is clicked
    $j('table#' + inID + ' tbody tr span').mousedown(function() 
    {
      $j($j(this).parents('tr')[0]).trigger('mousedown');
    });
  });
}

//..........................................................................

/* toggle the visibility of the element */
function toggle(inElement)
{
  if(!inElement.style.display || inElement.style.display == 'none')
    inElement.style.display = 'block';
  else
    inElement.style.display = 'none';
}

/* highlight the attachment value */
function highlightValues(inName)
{
  if(document.getElementById(inName) != null)
    document.getElementById(inName).style.color = 'red';  
  else
    for(i = 1; document.getElementById(inName + i) != null; i++)
      document.getElementById(inName + i).style.color = 'red';  
}

/* unhighlight the attachment value */
function unhighlightValues(inName)
{
  if(document.getElementById(inName) != null)
    document.getElementById(inName).style.color = 'white';
  else
    for(i = 1; document.getElementById(inName + i) != null; i++)
      document.getElementById(inName + i).style.color = 'white';      
}

/* format the menu entry */
function formatMenu(inText)
{
  return "<div class=\"shadow\">" + inText 
        + "</div>" + inText;
}

/* format the submenu entry */
function formatSubmenu(inText)
{
  return "<div class=\"shadow\">" + inText 
        + "</div>" + inText;
}

//----- Item ---------------------------------------------------------------

/**
 * Create an item display.
 *
 * @param inID       the id of the item
 * @param inName     the name of the item
 * @param inImage    the image for the item
 * @param inWeight   the weight of the item
 * @param inChildren the children, i.e. items in a container
 * @param opt_character true if having a character as container, false if not
 *
 */
function Item(inID, inName, inImage, inWeight, inChildren)
{
  this._id        = inID;
  this._name      = inName;
  this._image     = inImage;
  this._weight    = inWeight;
  this._children  = inChildren;
  this._open      = false;
  this._offset    = null;
  this._before    = null;
  this._top       = null;
  this._middle    = null;
  this._bottom    = null;
  this._style     = "item";
  this._element   = null;
  this._parent    = null;
};

extend(Item, gui.Droppable, "_droppable")
extend(Item, gui.DropTarget, "_target")

Item._placeholder = null;
Item._current = null;
Item._table = null;

//--------------------------------- build ---------------------------------

/**
 * Build the item.
 *
 * @param inContainer the container the item is in
 * @param inDisplay   the display where to add the item
 * @param inTargets   the drop targets for this
 * @param inBoundary  the element marking the boundary for the dragging
 *
 */
Item.prototype.build = function(inContainer, inDisplay, inTargets, inBoundary)
{
  this._container = inContainer;

  this._element = this.createIcon();

  this._element.onclick = this.select.bind(this);
  
  gui.Droppable.call(this, this._element, inTargets, inBoundary);
  gui.DropTarget.call(this, this._element);
  
  inDisplay.appendChild(this._element);
};

//..........................................................................
//------------------------------ createIcon -------------------------------

/**
 * Create the icon display for the item.
 *
 * @param inClass the class to use for the item
 *
 * @return the element created
 *
 */ 
Item.prototype.createIcon = function(inClass)
{
  var element = document.createElement("div");

  element.className = this._style + " icon";
  element.__item    = this;
  
  gui.tooltip(element, "ID: " + this._id + ", Weight: " + this._weight);
  
  var wrapper = document.createElement("div");
  
  wrapper.className = "wrapper";
  wrapper.innerHTML = "<div class='display'>"
    + "<img class='display' src='" + this._image + "' />"
    + "</div>"
    + "<div class='name'>" + this._name + "</div>";
  
  element.appendChild(wrapper);

  return element;
}

//..........................................................................
//------------------------------- createRow -------------------------------

/**
 * Create the row to display for the item.
 *
 * @return the element created
 *
 */ 
Item.prototype.createRow = function()
{
  var row = document.createElement("tr");
  row.id = "item-" + this._id;
  
  if(this._container) 
    row.className = "child-of-item-" + this._container._id;
  
  var name = document.createElement("td");
  name.innerHTML = this._name;

  var weight = document.createElement("td");
  weight.innerHTML = this._weight;

  row.appendChild(name);
  row.appendChild(weight);

  return row;
}

//..........................................................................
//------------------------------ isTargeted -------------------------------

/**
 * Check if the item is the target of a current drop.
 *
 * @param inMouse the mouse position to check for
 *
 * @return true if the target, false if not
 *
 */
Item.prototype.isTargeted = function(inMouse)
{
  if(this._target.isTargeted.call(this, inMouse))
    return true;

  // check also if over the place holder
  if(Item._placeholder && Item._placeholder._target == this)
    return gui.isOver(Item._placeholder, inMouse);

  return false;
}

//..........................................................................
//---------------------------------- mark ----------------------------------

/**
 * Mark the target for beeing dropped upon.
 *
 * @param inMouse the position of the mouse as {x: x, y: y}
 *
 */
Item.prototype.mark = function(inSource, inMouse)
{
  var marked = this._target.mark.call(this, inMouse);

  if(!Item._placeholder)
  {
    // create the dummy placeholder
    Item._placeholder              = document.createElement("div");
    Item._placeholder.className    = "placeholder";

    // fix width of the placeholder
    Item._placeholder.style.width  = inSource._element.clientWidth + "px";
    Item._placeholder.style.height = inSource._element.clientHeight + "px"; 
  }

  if(marked)
  {
    // store the boundary positions for selections
    var pos = gui.position(this._element);

    this._left   = pos.x + 0.33 * this._element.offsetWidth;
    this._middle = pos.x + 0.5 * this._element.offsetWidth;
    this._right  = pos.x + 0.66 * this._element.offsetWidth;
    
    Item._placeholder._target = this;

    if(inMouse.x < this._middle)
    {
      this._element.parentNode.insertBefore(Item._placeholder, 
                                            this._element);
      this._before = true;
    }
    else
    {
      this._element.parentNode.insertAfter(Item._placeholder,
                                           this._element);
    
      this._before = false;
    }
  }
  else
  {
    if(this._before == false && inMouse.x < this._left)
    {
      this._element.parentNode.insertBefore(Item._placeholder, 
                                            this._element);
      
      this._before = true;
    }
    else
      if(this._before == true && inMouse.x > this._right)
      {
        this._element.parentNode.insertAfter(Item._placeholder, 
                                             this._element);

        this._before = false;
      } 
  }
}

//..........................................................................
//-------------------------------- dropped ---------------------------------

/**
 * The element was actually dropped on this.
 *
 * @param inDroppable the droppable dropped onto this one 
 * @param inMouse     the position of the mouse as {x: x, y: y}
 *
 */
Item.prototype.dropped = function(inDroppable, inMouse)
{
  this._target.dropped.call(this, inDroppable, inMouse);

  this._before = null;
  inDroppable._element.style.position = "relative";
  inDroppable._element.style.top = "0";
  inDroppable._element.style.left = "0";

  var sibling = null;
  if(Item._placeholder == this._element.previousSibling)
  {
    if(this._element.previousSibling.previousSibling &&
       this._element.previousSibling.previousSibling.__item)
      sibling = this._element.previousSibling.previousSibling.__item._id;
  }
  else
    if(this._element.nextSibling == Item._placeholder)
      sibling = this._id;

  // add the item to the page again
  Item._placeholder.parentNode.replaceChild(inDroppable._element, 
                                            Item._placeholder);

  // send the message to the server (we have to deal with the target here,
  // because a Container can call this as well)
  eval(ajax("/actions/move", 
            { id: inDroppable._id, 
              target: this._container && this._container._container ? 
                this._container._id : null, sibling: sibling }, null));
}

//..........................................................................
//--------------------------------- select ---------------------------------

/**
 * Select the item. This will display the items details.
 *
 * @param inEvent the event that lead to the selection
 *
 */
Item.prototype.select = function(inEvent)
{
  // prevent bubbling 
  inEvent.stopPropagation();

  if(Item.current)
    Item.current.unselect(this);

  Item.current = this;
  gui.addStyle(this._element.firstChild, 'selected');

  var desc = $('item-desc');

  // show the current item to edit
  if(desc)
    desc.innerHTML = ajax("/entry/item/" + this._id + "?body&short", null, 
                          null);
}

//..........................................................................
//-------------------------------- unselect --------------------------------

/**
 * Unselect the item.
 *
 * @param inNew the new item that will be selected
 *
 */
Item.prototype.unselect = function(inNew)
{
  // currently nothing to do
}

//..........................................................................
//-------------------------------- initiate --------------------------------

/**
 * Initiate the dragging process.
 *
 */
Item.prototype.initiate = function(inEvent)
{
  this._droppable.initiate.call(this, inEvent);

  // show the containers to be able to drag to
  $('containers').style.display = "block";

  // hide tooltip
  this._element.__tooltip.style.display = "none";
};

//..........................................................................
//---------------------------------- drop ----------------------------------

/**
 * Drop the element.
 *
 * @param inEvent the event responsible for the action
 *
 */
Item.prototype.drop = function(inEvent)
{
  this._droppable.drop.call(this, inEvent);

  // remove the placeholder in any case
  if(Item._placeholder.parentNode)
    Item._placeholder.parentNode.removeChild(Item._placeholder);  

  // remove styles
  gui.removeStyle(this._containerElement, "hover");
  gui.removeStyle(this._element, "hover");

  $('containers').style.display = "none";
}

//..........................................................................

//..........................................................................
//----- Container ----------------------------------------------------------

/**
 * Create a Container display.
 *
 * @param inID       the id of the item
 * @param inName     the name of the item
 * @param inImage    the image for the item
 * @param inWeight   the weight of the item
 * @param inChildren the children, i.e. items in a container
 *
 */
var guru = null;
function Container(inID, inName, inImage, inWeight, inChildren)
{
  Item.call(this, inID, inName, inImage, inWeight, inChildren);

  this._style            = "container";
  this._current          = null;
  this._children         = inChildren;
  this._containerElement = this.createIcon();
  this._title            = null;

  // build up the display for the children
  for(var i = 0; i < inChildren.length; i++)
    this._children[i]._parent = this;

  // add the container to the list of containers
  $('containers').insertBefore(this._containerElement, 
                               $('containers').firstChild.nextSibling);

  Container._containers.push(this);
  open();
};

extend(Container, Item);

// the currently shown container
Container._current = null;

// all the containers
Container._containers = [];

//--------------------------------- build ---------------------------------

/**
 * Build the item.
 *
 * @param inContainer   the container the item is in
 * @param inDisplay     the display where to add the item
 * @param inTargets     the possible drop targets
 * @param inBoundary    the element marking hte boundary for the dragging
 *
 */
Container.prototype.build = function(inContainer, inDisplay, inTargets, 
                                     inBoundary, opt_character)
{
  Item.prototype.build.call(this, inContainer, inDisplay, inTargets, 
                            inBoundary);

  this._element.ondblclick = this.open.bind(this);
};

//..........................................................................
//---------------------------------- mark ----------------------------------

/**
 * Mark the target for beeing dropped upon.
 *
 * @param inSource the object that initiated the marking 
 * @param inMouse  the position of the mouse as {x: x, y: y}
 *
 * @return true if marked, false if not
 * 
 */
Container.prototype.mark = function(inSource, inMouse)
{
  // over the special container
  if(gui.isOver(this._containerElement, inMouse, true))
  {
    this._super._target.mark.call(this, inSource, inMouse);
    gui.addStyle(this._containerElement, "hover");
  }
  else
  {
    this._super.mark.call(this, inSource, inMouse);

    gui.removeStyle(this._containerElement, "hover");
    var pos = gui.position(this._element);

    // over the container or over the placeholder?
    if(inMouse.x > pos.x + 15 
       && inMouse.x < pos.x + this._element.offsetWidth - 15)
    {
      // over the container
      gui.addStyle(this._element, "hover");
    }
    else    
    {
      // over the placeholder
      gui.removeStyle(this._element, "hover");
      
      this._super.mark.call(this, inSource, inMouse);
    }
  }
};

//..........................................................................
//--------------------------------- unmark ---------------------------------

/**
 * Unmark the target for beeing dropped upon.
 *
 * @param inSource the object that initiated the unmarking 
 * @param inMouse  the position of the mouse as {x: x, y: y}
 *
 */
Container.prototype.unmark = function(inSource, inMouse)
{
  this._super.unmark.call(this, inSource, inMouse);  

  gui.removeStyle(this._element, "hover");
  gui.removeStyle(this._containerElement, "hover");
};

//..........................................................................
//-------------------------------- dropped ---------------------------------

/**
 * The element was actually dropped on this.
 *
 * @param inDroppable the droppable dropped onto this one 
 * @param inMouse     the position of the mouse as {x: x, y: y}
 *
 */
Container.prototype.dropped = function(inDroppable, inMouse)
{
  if(!gui.isOver(this._containerElement, inMouse, true))
  {    
    var pos = gui.position(this._element);

    // over the container or over the placeholder?
    if(inMouse.x > pos.x + 15 
       && inMouse.x < pos.x + this._element.offsetWidth - 15)
      // inside the container
      this._super._target.dropped.call(this, inDroppable, inMouse);
    else
    {
      // outside the container
      this._super.dropped.call(this, inDroppable, inMouse);
      
      // moving is handled in Item
      return;
    }
  }

  // send the message to the server
  eval(ajax("/actions/move", 
            { id: inDroppable._id, 
              target: this._container ? this._id : null},
            null));
  
  // move the item display to its appropriate place in the container
  var children = inDroppable._parent._children;
  children.remove(inDroppable);
  
  this._children.push(inDroppable);
  inDroppable._parent = this;
};

//..........................................................................
//---------------------------------- open ----------------------------------

/**
 * Open the container and display its contents.
 *
 */
Container.prototype.open = function()
{
  if(Container._current)
    Container._current.close();

  // show the title, if necessary
  if(!this._title)
  {
    this._title = document.createElement("div");
    this._title.appendChild(this.createIcon());
    
    if(this._container) 
    {
      var close         = document.createElement("img");
      close.src         = "/icons/undefine.png";
      close.alt         = "Close";
      close.title       = "Close Container";
      close.className   = "overlay close";
      close.__container = this;
      close.onclick     = function() 
        { this.__container.close(); this.__container._container.open(); };

      this._title.appendChild(close);
    }

    $('item-title').appendChild(this._title);
  }

  this._title.style.display = "";

  if(!this._items)
  {
    this._items = document.createElement("div");

    // must add it to page before building items or boundary will not compute
    $('elements').appendChild(this._items);

    var targets = [];
    for(var i = 0; i < this._children.length; i++)
      targets.push(this._children[i]);
    
    for(var i = 0; i < Container._containers.length; i++)
      targets.push(Container._containers[i]);

    for(var i = 0; i < this._children.length; i++)
      this._children[i].build(this, this._items, targets, document);
  }

  this._items.style.display = "";

  Container._current = this;
};

//..........................................................................
//--------------------------------- close ----------------------------------

/**
 * Close the container and hide its contents
 *
 */ 
Container.prototype.close = function()
{
  if(this._title)
    this._title.style.display = "none";

  if(this._items)
  {    
    // just setting it to not display does not work as adding additional nodes
    // fails
    this._items.parentNode.removeChild(this._items);
    this._items = null;
  }
};

//..........................................................................
//------------------------------ isTargeted -------------------------------

/**
 * Check if the item is the target of a current drop.
 *
 * @param inMouse the mouse position to check for
 *
 * @return true if the target, false if not
 *
 */
Container.prototype.isTargeted = function(inMouse)
{
  if(gui.isOver(this._containerElement, inMouse, true))
    return true;

  return this._super.isTargeted.call(this, inMouse);
}

//..........................................................................

//..........................................................................
//----- admin --------------------------------------------------------------

var admin = {};

admin.addEvent = function(inText, inSeconds)
{
  var events = $('admin-events');
  
  var event = document.createElement("div");

  event.className = "event";
  event.innerHTML = "<div class='date'>" + niceDate(inSeconds)
    + "</div><div class='text'>" + inText + "</div>";
  
  events.insertBefore(event, events.firstChild);
};

admin.states = [];
admin.addLog = function(inType, inText, inSeconds)
{
  var logs = $('admin-log');

  if(inType != "STATUS" || !logs.lastChild)
    logs.insertBefore(admin.createEntry(inType, inText, inSeconds, true), 
                      logs.firstChild);
  else
    admin.states.push([inSeconds, inText]);
};

admin.createEntry = function(inType, inText, inSeconds, inSubs)
{
  var log = document.createElement("div");

  log.__type    = inType;
  log.className = "log " + inType;
  log.innerHTML = "<div class='date'>" + niceDate(inSeconds)
    + "</div>"
    + (inSubs && admin.states.length > 0 ? 
       "<img src='/icons/states.png' alt='Toggle States' "
       + "title='Toggle States' class='states' "
       + "onclick='admin.toggleStates(this)'/>" 
       : "") + "<div class='text'>" + inText + "</div>";

  if(inSubs && admin.states.length > 0)
  {
    var sub = document.createElement("div");

    sub.className = "states";
    sub.style.display = "none";

    for(var i = 0; i < admin.states.length; i++)
      sub.appendChild(admin.createEntry("STATUS", admin.states[i][1], 
                                        admin.states[i][0], false));

    log.appendChild(sub);
    admin.states = [];
  }

  return log;
};

admin.toggleStates = function(inLog)
{
  inLog = inLog.parentNode;
  
  if(inLog.lastChild.style.display != "none")
    inLog.lastChild.style.display = "none";
  else
    inLog.lastChild.style.display = "block";
};

admin.show = function(inType)
{
  var logs = $('admin-log');

  for(var i = 0; i < logs.childNodes.length; i++)
  {    
    var child = logs.childNodes[i];

    if(inType == "COMPLETE" 
       || (inType == "DEBUG" && child.__type != "COMPLETE")
       || (inType == "STATUS" 
           && child.__type != "DEBUG" && child.__type != "COMPLETE")
       || (inType == "INFO" 
           && (child.__type == "INFO" || child.__type == "WARNING" 
               || child.__type == "ERROR"))
       || (inType == "WARNING" 
           && (child.__type == "ERROR" || child.__type == "WARNING"))
       || (inType == "ERROR" && child.__type == "ERROR"))
      child.style.display = "block";
    else 
    {
      child.style.display = "none";
      window.status += inType + ":" + child.__type + " / ";
    }
  }
};

//..........................................................................





