St = new Object;

St.Window = function(title) {
  var self = this;
  var offset, box;
  
  St.Window.instances.push(this);
	offset = St.Window.instances.length * 25 + 'pt';

  this.root = document.createElement('div');
  this.root.className = 'st-window'
  this.root.style.top = offset;
  this.root.style.left = offset;

  this.handle = document.createElement('div');
  this.handle.className = 'st-handle';
  
  box = document.createElement('a');
  box.className = 'st-control-close';
  box.href = 'javascript:void(0)';
  box.onclick = function() {self.close()};
  box.appendChild(document.createTextNode('x'));
  
  this.handle.appendChild(box);
  this.handle.appendChild(document.createTextNode(title));
  this.root.appendChild(this.handle);
    
  this.content = document.createElement('div');
  this.content.className = 'st-content';
  this.root.appendChild(this.content);
  document.body.appendChild(this.root);
  this.raise();
  
  this.handle.onmousedown = function(e) {self.startDrag(e)};
}

St.Window.instances = new Array;

St.Window.prototype.startDrag = function(e)
{
	this.x = e.clientX;
	this.y = e.clientY;
	this.raise();
	var self = this;
	this.savedHandler = window.onmousemove;
  window.onmousemove = function(e) {self.drag(e)};
	this.handle.onmouseup = function(e) {self.endDrag(e)};
};

St.Window.prototype.drag = function(e)
{
	var dx = e.clientX - this.x;
	var dy = e.clientY - this.y;
	this.root.style.left = this.root.offsetLeft + dx + 'px';
	this.root.style.top = this.root.offsetTop + dy + 'px';
	this.x = e.clientX;
	this.y = e.clientY;
};

St.Window.prototype.endDrag = function(e)
{
	window.onmousemove = this.savedHandler;
	this.savedHandler = null;
	this.handle.onmouseup = null;
};

St.Window.prototype.raise = function()
{
	for (var i=0; i<St.Window.instances.length; i++)
	{
		St.Window.instances[i].root.style.zIndex = 0;
	}
	this.root.style.zIndex = 1;
};

St.Window.prototype.close = function()
{
  this.onclose();
  this.root.parentNode.removeChild(this.root);
};


St.Inspector = function(obj) {
  var type = typeof obj;
  if (type == 'object' || type == 'function')
    this.obj = obj;
  else 
  {
    this.obj = new Object;
    this.obj['<type>'] = type;
    this.obj['<value>'] = obj;
  }
}


St.Inspector.prototype.open = function(label)
{
  var self = this;
  var win, title, interval;
  title = label ? label : 'Inspector';
  
  win = new St.Window(title);
  this.root = win.content;
  this.root.appendChild(document.createElement('p'));
  this.update();
  
  interval = window.setInterval(function() {self.update()}, 500);
  win.onclose = function() {window.clearInterval(interval)}
};


St.Inspector.prototype.properties = function()
{
  var properties = new Array;
  properties.push(new St.Property('-prototype', this.obj.__proto__));
  for (var p in this.obj) 
		properties.push(new St.Property(p, this.obj[p]));
    
  return properties;
};

St.Inspector.prototype.update = function()
{
  var table = document.createElement('table');

 	var properties = this.properties();
  for (var i=0; i<properties.length; i++)
    properties[i].populateRow(table.insertRow(i));

	this.root.replaceChild(table, this.root.firstChild);
};



St.Property = function(name, value) {
  this.name = name;
  this.value = value;
}

St.Property.prototype.populateRow = function(row)
{
  var cell, text;
  cell = row.insertCell(-1);
  cell.className = 'st-label';
    
  text = document.createTextNode(this.name);
  cell.appendChild(text);
  
  cell = row.insertCell(-1);
  this.render(cell);
  
};

St.Property.prototype.shouldLink = function()
{
  return this.value instanceof Object ? true : false;
}

St.Property.prototype.render = function(cell)
{
  var limit = 40;
  var string, link, elipsis, text;
  var self = this;

  cell.className = 'st-value'
  try {string = '' + this.value}
  catch(e) {string = '[error printing value]'}
	if (string.length > limit) {
		string = string.slice(0,limit);
		string += ' ';
		elipsis = document.createElement('a');
		elipsis.className = 'st-elided';
		elipsis.href='javascript:void(0)';
//		link.onclick = function() {self.expand()}
		elipsis.appendChild(document.createTextNode('...'));
	}
	
	if (this.shouldLink())
  {
		link = document.createElement('a');
		link.className = 'st-value';
		link.href='javascript:void(0)';
		link.onclick = function() {St.inspect(self.value, self.name)};
		link.appendChild(document.createTextNode(string));
		cell.appendChild(link);
	}
	else
	{
	  cell.appendChild(document.createTextNode(string));  
	}
	
	if (link) cell.appendChild(link);
};



St.Property.prototype.isFunction = function()
{
  return this.value instanceof Function;
};

St.Property.prototype.isNull = function()
{
  return this.value == null;
}



St.inspect = function(obj, label) {
  new St.Inspector(obj).open(label);
}

St.log = function(val)
{
	if (window.console) {
		window.console.log(val);
	} else if (document.createEvent) {
			printfire=function(){}
	        printfire.args = arguments;
	        var ev = document.createEvent("Events");
	        ev.initEvent("printfire", false, true);
	        dispatchEvent(ev);
	} else {
		window.alert(val + "\n");
	}
}
