/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();

Dom = {
	get: function(elm) {
		if ( typeof elm === 'string' ) {
			return document.getElementById(elm);
		} else {
			return elm;
		}
	},
	add: function(elm, dest) {
		var elm = this.get(elm);
		var dest = this.get(dest);
		dest.appendChild(elm);
	},
	create: function(cfg) {
		if ( typeof cfg == 'string' ) {
			return document.createElement(cfg);
		} else {
			var elm;
			if ( cfg.tag == 'checkbox') {
				elm = document.createElement('input');
				elm.type = 'checkbox';
			} else {
				elm = document.createElement(cfg.tag);
			}
			if ( cfg.class1 ) elm.className = cfg.class1;
			if ( cfg.cls ) elm.className = cfg.cls;

			if ( cfg.id ) elm.id = cfg.id;
			if ( cfg.text ) elm.innerHTML = cfg.text;
			if ( cfg.name ) elm.name = cfg.name;
			if ( cfg.src ) elm.src = cfg.src;

			if ( cfg.href ) elm.href = cfg.href;
			if ( cfg.title ) elm.title = cfg.title;

			if ( cfg.type ) elm.type = cfg.type;
			if ( cfg.value ) elm.value = cfg.value;

			if ( cfg.parent ) Dom.add(elm, Dom.get(cfg.parent));
			if ( cfg.renderTo ) Dom.add(elm, Dom.get(cfg.renderTo));

			return elm;
		}
	}
};

Util = {
	isDefined: function(variable) {
		return typeof(variable) != 'undefined';
	},
	isEmpty: function(val) {
		return val == '';
	},
	loadURL: function(url){
		document.location.href = url;
	},
	isIE: function() {
		return /MSIE/.test(navigator.userAgent);
	}
}

var Field = Class.extend({

	init: function(cfg) {

		this.state = cfg.state || '';
		this.name = cfg.name;
		this.label = cfg.label || '';
		this.width = cfg.width || 198;
		this.height = cfg.height || 18;
		this.allowBlank = true;
		this.readOnly = false;
		this.visible = true;
		this.theme = cfg.theme || 'blue';
		this.title = cfg.title || '';

		this.baseCls = this.fieldType;
		this.blurCls = this.theme + '-' + this.baseCls;
		this.focusCls = this.theme + '-' + this.baseCls + '-focus';
		this.errorCls = this.theme + '-' + this.baseCls + '-error';
		this.disableCls = this.theme + '-' + this.baseCls + '-disabled';

		if ( Util.isDefined(cfg.readOnly) ) {
			this.readOnly = cfg.readOnly;
		}

		if ( Util.isDefined(cfg.visible) ) {
			this.visible = cfg.visible;
		}

		if ( cfg.text ) {
			this.text = cfg.text;
		}

		if ( Util.isDefined(cfg.allowBlank) ) {
			this.allowBlank = cfg.allowBlank;
		}

		this.standAlone = true;
		if ( Util.isDefined(cfg.standAlone) ) {
			this.standAlone = cfg.standAlone;
		}
		this.handler = cfg.handler || function() {};

		this.createMainCont(cfg);
		this.createElm();
		this.createMsgCont();

		if ( cfg.value ) {
			this.value = cfg.value;
			this.setValue(this.value);
		}

		if ( this.state == 'disabled' ) {
			this.disable();
		} else {
			this.enable();
		}
	},

	createMainCont: function(cfg) {
		this.mainCont = Dom.create({
			tag: 'span',
			title: this.title
		});
		if ( cfg.renderTo ) {
			this.render(cfg.renderTo);
		}
	},

	createMsgCont: function() {
		if ( this.standAlone ) {
			this.msgCont = Dom.create({
				tag: 'span',
				cls: 'field-error',
				renderTo: this.mainCont
			});
		}
	},

	error: function(msg) {
		var fld = this;
		var elm = fld.elm;
		$(elm).attr('class', fld.baseCls + ' ' + fld.errorCls);
		if ( this.standAlone ) {
			this.msgCont.innerHTML = msg;
		}
	},

	setValue: function(val) {
		this.elm.value = val;
	},

	getValue: function() {
		return this.elm.value;
	},

	render: function(renderTo) {
		Dom.add(this.mainCont, Dom.get(renderTo));
	},

	enable: function() {
		var fld = this;
		var elm = fld.elm;
		elm.disabled = false;

		$(elm).attr('class', fld.baseCls + ' ' + fld.blurCls);
		$(elm).focus(function() {
			$(elm).attr('class', fld.baseCls + ' ' + fld.focusCls);
			if ( fld.standAlone ) {
				fld.msgCont.innerHTML = '';
			}
			if ( fld.hFocus ) {
				fld.hFocus(fld);
			}
		});

		$(elm).blur(function() {
			$(elm).attr('class', fld.baseCls + ' ' + fld.blurCls);
			if ( fld.standAlone ) {
				fld.msgCont.innerHTML = '';
			}
			if ( fld.hBlur ) {
				fld.hBlur(fld);
			}
		});
	},

	disable: function() {
		var fld = this;
		var elm = fld.elm;
		elm.blur();
		elm.disabled = true;
		$(elm).attr('class', fld.baseCls + ' ' + fld.disableCls);
		elm.onfocus = null;
		elm.onblur = null;
	},

	validate: function() {
		var v = this.getValue();
		if ( !this.allowBlank ) {
			if ( Util.isEmpty(this.getValue()) ) {
				this.error('Това поле е задължително!');
				return false;
			}
		}
		return true;
	},

	createElm: function() {
		this.elm = Dom.create({
			tag: this.fieldType,
			name: this.name,
			type: this.type,
			renderTo: this.mainCont
		});
		this.elm.style.width = this.width + 'px';
		this.elm.style.height = this.height + 'px';
		this.elm.readOnly = this.readOnly;
	}

});

var TextField = Field.extend({
	init: function(cfg) {
		this.fieldType = 'input';
		this.type = cfg.type || 'text';
		this._super(cfg);
	},

	addListener: function(eventName, handler) {
		var elm = this.elm;
		if ( eventName == 'keypress' ) {
			elm.onkeypress = handler;
		} else if ( eventName == 'enterpress' ) {
			elm.onkeypress = function(e) {
				var key;
				if ( window.event ) {
				// Internet Explorer
					key = window.event.keyCode;
				} else {
				// Mozilla Firefox
					key = e.which;
				}
				if ( key == 13 ) {
					return handler();
				}
			}
		} else if ( eventName == 'click' ) {
			elm.onclick = handler;
		} else if ( eventName == 'focus' ) {
			this.hFocus = handler;
		} else if ( eventName == 'blur' ) {
			this.hBlur = handler;
		}
	},

	render: function(renderTo) {
		this._super(renderTo);
	}

});

function DropDownPanel(cfg) {

	this.create = function(cfg) {
		this.noBorder = cfg.noBorder || false;
		this.theme = cfg.theme || 'blue';
		this.elm = Dom.get(cfg.renderTo);

		this.elm.className = 'dropdown-container ' + this.theme + '-dropdown-container';

		if ( this.noBorder ) {
			this.elm.style.border = '0 none';
		}

		if ( cfg.height ) {
			this.elm.style.height = cfg.height + 'px';
		} else {
			this.elm.style.height = 'auto';
		}

		if ( cfg.width ) {
			this.elm.style.width = cfg.width + 'px';
		} else {
			this.elm.style.width = 'auto';
		}

		this.visible = false;
	}

	this.show = function() {
		if ( ddp ) {
			ddp.hide();
		}
		ddp = this;
		this.elm.style.visibility = 'visible';
		this.visible = true;
	}

	this.hide = function() {
		ddp = null;
		this.elm.style.visibility = 'hidden';
		this.visible = false;
	}

	this.create(cfg);
}

function ColorView(cfg) {

	this.create = function(cfg) {
		this.itemsCont = Dom.create({
			tag: 'div',
			cls: 'colorview-container',
			renderTo: Dom.get(cfg.renderTo)
		});

		if ( cfg.handler ) {
			this.handler = cfg.handler;
		}

		this.updateItems(cfg.items, cfg.values);

	}

	this.updateItems = function(items, values) {

		var listView = this;
		var itemsCont = this.itemsCont;

		//remove old content
		while( itemsCont.hasChildNodes() ) {
			itemsCont.removeChild(itemsCont.firstChild);
		}

		this.colorConts = [];

		for ( var i = 0; i < items.length; i++ ) {
			var item = items[i];
			this.colorConts
			var colorCont = Dom.create({
				tag: 'span',
				cls: 'color',
				title: values[i],
				renderTo: this.itemsCont
			});
			colorCont.n = i;

			var img = Dom.create({
				tag: 'img',
				src: item,
				renderTo: colorCont
			});

			this.initItem(colorCont);

		}
	},

	this.initItem = function(item) {
		var cv = this;
		item.onmouseover = function() {
			if ( this.n != cv.selectedItem )
				this.className = 'color-hover';
		}
		item.onmouseout = function() {
			if ( this.n != cv.selectedItem )
				this.className = 'color';
		}
		item.onclick = function() {
			if ( this.n != cv.selectedItem ) {
				if ( typeof(cv.selectedItem) != "undefined" )
					cv.itemsCont.childNodes[cv.selectedItem].className = 'color';
				cv.selectedItem = this.n;
				this.className = 'color-selected';
			}
			if ( cv.handler )
				cv.handler(cv.selectedItem);
		}
	}

	this.create(cfg);
}

var TriggerField = Field.extend({
	init: function(cfg) {
		this.btnIcon = this.btnIcon || 'magnifier-glass';
		this.onEnterPress = cfg.onEnterPress || function() {};
		this._super(cfg);
	},

	enable: function() {
		this.elm.enable();
		this.btn.enable();
	},

	disable: function() {
		this.elm.disable();
		this.btn.disable();
	},

	getValue: function() {
		return this.elm.getValue();
	},

	setValue: function(val) {
		this.elm.setValue(val);
	},

	error: function(msg) {
		this.elm.error();
		this.btn.error();
		this.msgCont.innerHTML = msg;
	},

	createElm: function() {
		var elmCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});

		var btnCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});
		Dom.create({
			tag: 'br',
			cls: 'clear',
			renderTo: this.mainCont
		});

		this.elm = new TextField({
			renderTo: elmCont,
			theme: this.theme,
			standAlone: false,
			readOnly: this.readOnly,
			width: this.width - 23,
			name: this.name
		});
		this.elm.elm.style.borderRight = '0px none';

		var tf = this;
		this.btn = new ToggleButton({
			renderTo: btnCont,
			theme: this.theme,
			type: 'icon',
			width: 12,
			handler: function() {
				tf.handler(tf);
			},
			icon: this.btnIcon
		});
		var btn = this.btn;
		$(btn.cnt).css('border-left',  'none');
		this.elm.addListener('focus', function() {
			btn.select();
			tf.msgCont.innerHTML = '';
		});
		this.elm.addListener('blur', function() {
			btn.deselect();
			tf.msgCont.innerHTML = '';
		});
		this.elm.addListener('enterpress', function() {
			tf.onEnterPress(tf);
		});
	}

});

//defining alias names
var ColorField = ColorPicker = TriggerField.extend({

	init: function(cfg) {
		this.btnIcon = 'colorpicker-icon';
		this.items = cfg.items;
		this.values = cfg.values;
		cfg.readOnly = true;

		this.ownHandler = cfg.handler || function() {};
		cfg.handler = function(cb) {
			if ( cb.ddp.visible ) {
				cb.ddp.hide();
			} else {
				cb.ddp.show();
			}
		}

		this._super(cfg);
	},

	createElm: function() {
		this._super();
		var mCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});

		var cb = this;
		this.lv = new ColorView({
			renderTo: mCont,
			handler: function(n) {
				cb.setValue(cb.values[n]);
				cb.ddp.hide();
				cb.ownHandler(cb);
			},
			values: this.values,
			items: this.items
		});

		this.ddp = new DropDownPanel({
			renderTo: mCont,
			width: 265
		});

		//hack: because of the stupid ie
		if ( this.items.length > 42 ) {
			this.ddp.elm.style.height = '184px';
		}
		var ddp = this.ddp;
		this.elm.addListener('click', function() {
			ddp.hide();
		});
	}

});

//defining alias names
var ComboBox = ComboField = TriggerField.extend({

	init: function(cfg) {
		this.btnIcon = 'down-arrow';
		this.items = cfg.items;
		this.values = [];
		this.useValues = false;

		if ( cfg.values ) {
			this.loadValues(cfg.values);
		}

		this.onChange = cfg.onChange || function() {};
		this.ownHandler = cfg.handler || function() {};

		cfg.handler = function(cb) {
			if ( cb.ddp.visible ) {
				cb.ddp.hide();
			} else {
				cb.ddp.show();
			}
		}

		this._super(cfg);
	},

	loadValues: function(values) {
		this.useValues = true;
		for ( var i = 0; i < values.length; i++ ) {
			this.values[this.items[i]] = values[i];
		}
	},

	createElm: function() {
		this._super();
		var mCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});

		var cb = this;
		this.lv = new ListView({
			theme: this.theme,
			renderTo: mCont,
			handler: function(val) {
				var oldVal = cb.getValue();
				cb.setValue(val);
				cb.ddp.hide();
				cb.ownHandler(cb);
				if ( oldVal != val ) {
					cb.onChange(cb);
				}
			},
			items: this.items
		});

		this.ddp = new DropDownPanel({
			renderTo: mCont,
			theme: this.theme,
			width: this.width + 3
		});

		//hack: because of the stupid ie
		if ( this.items.length > 7 ) {
			this.ddp.elm.style.height = '184px';
		}
		var ddp = this.ddp;
		this.elm.addListener('click', function() {
			ddp.hide();
		});
	},

	getValue: function() {
		if ( Util.isEmpty(this._super()) ) {
			return this._super();
		} else if ( this.useValues ) {
			return this.values[this.elm.getValue()];
		} else {
			return this._super();
		}
	}

});

function Calendar(cfg) {

	this.create = function(cfg) {
		var calendar = this;
		this.handler = cfg.handler;

		var t = Dom.create({
			tag: 'table',
			class1: 'calendar',
			parent: Dom.get(cfg.renderTo)
		});
		t.cellPadding = '0px';
		t.cellSpacing = '0px';

		var tb = Dom.create('tbody');
		var tr = Dom.create('tr')
		var td = Dom.create({tag: 'td', class1: 'calendar-navigation'});
		Dom.add(tb, t);
		Dom.add(tr, tb);
		Dom.add(td, tr);

		var t1 = Dom.create('table');
		t1.width = '100%';
		var tb1 = Dom.create('tbody');
		var tr1 = Dom.create('tr')
		var td1 = Dom.create('td');
		td1.width = '25px';
		Dom.add(t1, td);
		Dom.add(tb1, t1);
		Dom.add(tr1, tb1);
		Dom.add(td1, tr1);

		var s1 = Dom.create('span');
		Dom.add(s1, td1);
		td1 = Dom.create('td');
		td1.align = 'center';
		Dom.add(td1, tr1);
		this.dateCont = Dom.create({
			tag: 'span',
			parent: td1,
			class1: 'calendar-info'
		});

		td1 = Dom.create('td');
		td1.width = '25px';
		Dom.add(td1, tr1);
		var s3 = Dom.create('span');
		Dom.add(s3, td1);

		tr = Dom.create('tr');
		Dom.add(tr, tb);
		td = Dom.create({tag: 'td', class1: 'calendar-header'});
		Dom.add(td, tr);
		for ( var i = 0; i < this.wDays.length; i++ ) {
			var wdayElm = Dom.create({
				tag: 'span',
				class1: 'wday',
				text: this.wDays[i],
				parent: td
			});
			if ( i > 4 ) {
				wdayElm.style.color = '#ff6464';
			}
		}

		tr = Dom.create({
			tag: 'tr',
			parent: tb
		});

		this.daysCont = Dom.create({
			tag: 'td',
			parent: tr,
			class1: 'calendar-content'
		});

		this.date = new Date();
		this.updateDays();
		this.updateDate();

		new Button({
			renderTo: s3,
			type: 'icon',
			icon: 'right-arrow',
			handler: function() {
				calendar.nextMonth();
				calendar.updateDays();
				calendar.updateDate();
			}
		});

		new Button({
			renderTo: s1,
			type: 'icon',
			icon: 'left-arrow',
			handler: function() {
				calendar.prevMonth();
				calendar.updateDays();
				calendar.updateDate();
			}
		});

	}

	this.months = ['Януари', 'Февруари', 'Март', 'Април', 'Май', 'Юни', 'Юли', 'Август', 'Септември', 'Октомври', 'Ноември', 'Декември'];
	this.wDays = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Нд'];

	this.updateDate = function() {
		var date = this.date;
		var month = this.months[date.getMonth()];
		var year = date.getFullYear();
		this.dateCont.innerHTML = month + ' ' + year;
	}

	this.setDate = function(date) {
		this.date = date;
		this.updateDays();
		this.updateDate();
	}

	this.updateDays = function() {
		var date = this.date;

		//remove old content
		while( this.daysCont.hasChildNodes() ) {
			this.daysCont.removeChild(this.daysCont.firstChild);
		}

		//create initial empty positions
		for ( var i = 0; i < this.daysToSkip(date); i++ ) {
			Dom.create({
				tag: 'span',
				class1: 'day',
				parent: this.daysCont
			});
		}

		var j = this.daysToSkip(date);
		var nDay = date.getDate();
		for ( var i = 0; i < this.daysInMonth(date); i++ ) {
			var iDay = i + 1;

			var elmDay = Dom.create({
				tag: 'span',
				class1: 'day',
				text: iDay,
				parent: this.daysCont
			});

			//todo: obviously this can be improved
			if ( iDay == nDay ) {
				elmDay.className = 'day-selected';
				this.selectedDay = elmDay;
			}

			this.initDay(elmDay);

			j++;
			if ( j % 7 == 0 ) {
				Dom.create({
					tag: 'br',
					parent: this.daysCont
				});
			}
		}
	}

	this.initDay = function(elmDay) {
		var calendar = this;
		elmDay.onmouseover = function() {
			this.className = 'day-hover';
		}

		elmDay.onmouseout = function() {
			if ( calendar.selectedDay.innerHTML == this.innerHTML ) {
				this.className = 'day-selected';
			} else {
				this.className = 'day';
			}
		}

		elmDay.onclick = function() {
			if ( calendar.selectedDay ) {
				calendar.selectedDay.className = 'day';
			}
			this.className = 'day-selected';
			calendar.selectedDay = this;
			var day = parseInt(this.innerHTML);
			calendar.date.setDate(day);

			if ( calendar.handler ) {
				calendar.handler(calendar);
			}
		}

	}

	this.daysToSkip = function(date) {
		var month = date.getMonth();
		var year = date.getFullYear();
		//first day of month
		var firstDay = new Date(year, month, 1);
		var skipDays = firstDay.getDay();

		//normalize skipDays according bulgarian standart
		if ( skipDays == 0 ) {
			skipDays = 6;
		} else {
			skipDays--;
		}
		return skipDays
	}

	this.daysInMonth = function(date) {
		//get the next month
		var month = date.getMonth() + 1;
		var year = date.getYear();
		return new Date(year, month, 0).getDate();
	}

	this.nextMonth = function() {
		var oldDate = this.date;
		var day = oldDate.getDate();
		this.date = new Date(oldDate.getFullYear(), oldDate.getMonth() + 1, 1);
		var newDate = this.date;
		if ( this.daysInMonth(newDate) < oldDate.getDate() ) {
			day = this.daysInMonth(newDate);
		}
		this.date.setDate(day)
	}

	this.prevMonth = function() {
		var oldDate = this.date;
		var day = oldDate.getDate();
		this.date = new Date(oldDate.getFullYear(), oldDate.getMonth() - 1, 1);
		var newDate = this.date;
		if ( this.daysInMonth(newDate) < oldDate.getDate() ) {
			day = this.daysInMonth(newDate);
		}
		this.date.setDate(day)
	}

	this.create(cfg);
}

//defining alias names
var DateField = DatePicker = TriggerField.extend({

	init: function(cfg) {
		cfg.width = cfg.width || 100;
		this.btnIcon = 'calendar-icon';
		this._super(cfg);
	},

	setDate: function(date) {
		var d = date;
		var dStr = d.getDate() + '.';
		var m = d.getMonth() + 1;
		if ( m < 10 ) m = '0' + m;
		dStr += m + '.';
		dStr += d.getFullYear();
		this.elm.setValue(dStr);
		this.calendar.setDate(date);
	},

	createElm: function() {
		this._super();

		var mCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});

		var df = this;
		var elm = this.elm;
		this.calendar = new Calendar({
			renderTo: mCont,
			handler: function(calendar) {
				var d = calendar.date;
				var dStr = d.getDate() + '.';
				var m = d.getMonth() + 1;
				if ( m < 10 ) m = '0' + m;
				dStr += m + '.';
				dStr += d.getFullYear();
				elm.setValue(dStr);
			}
		});

		this.ddp = new DropDownPanel({
			renderTo: mCont,
			noBorder: true
		});

		var ddp = this.ddp;
		this.elm.addListener('click', function() {
			ddp.hide();
		});

		this.handler = function(df) {
			if ( df.ddp.visible ) {
				df.ddp.hide();
			} else {
				df.ddp.show();
			}
		}
	}

});

//defining alias names
var ItemSelector = TriggerField.extend({

	init: function(cfg) {
		this.btnIcon = 'selector-icon';
		this.items = cfg.items;
		this.values = cfg.values;

		if ( cfg.values ) {
			for ( var i = 0; i < this.items.length; i++ ) {
				this.values[this.items[i]] = cfg.values[i];
			}
		}

		cfg.readOnly = true;

		this.ownHandler = cfg.handler;
		cfg.handler = function(cb) {
			if ( cb.ddp.visible ) {
				cb.ddp.hide();
			} else {
				cb.ddp.show();
			}
		}

		this._super(cfg);
	},

	createElm: function() {
		this._super();
		var mCont = Dom.create({
			tag: 'span',
			renderTo: this.mainCont
		});

		var is = this;
		var isCont = Dom.create({
			tag: 'span',
			cls: 'items-container',
			renderTo: mCont
		});
		for ( var i = 0; i < this.items.length; i++ ) {
			var item = this.items[i];
			var iCont = Dom.create({
				tag: 'span',
				text: item,
				cls: 'item',
				renderTo: isCont
			});

			iCont.onmouseover = function() {
				if ( !this.selected ) {
					this.className = 'item-hover';
				}
			}

			iCont.onmouseout = function() {
				if ( !this.selected ) {
					this.className = 'item';
				}
			}

			iCont.onclick = function(e) {
				if ( this.selected ) {
					is.removeValue(this.innerHTML);
					this.className = 'item-hover';
				} else {
					is.addValue(this.innerHTML);
					this.className = 'item-selected';
				}
				this.selected = !this.selected;
				if ( is.ownHandler ) {
					is.ownHandler(is, this.innerHTML, this.selected);
				}

				//prevent event propagation
				if (!e) var e = window.event;
				e.cancelBubble = true;
				if (e.stopPropagation) e.stopPropagation();

			}
		}

		this.ddp = new DropDownPanel({
			renderTo: mCont,
			width: 201
		});

		//hack: because of the stupid ie
		if ( this.items.length > 42 ) {
			this.ddp.elm.style.height = '184px';
		}
		var ddp = this.ddp;
		this.elm.addListener('click', function() {
			ddp.hide();
		});
	},

	addValue: function(val) {
		this.setValue(this.getValue() + val + ', ');
	},

	// this has to be improved
	removeValue: function(val) {
		this.setValue(this.getValue().replace(val + ', ', ''));
	},

	translate: function(val) {
		return this.values[val];
	}
// 	setValue: function(n) {
// 		this._super(this.values[n]);
// 	}

});

var Button = Class.extend({

	init: function(cfg) {

		this.height = cfg.height || 17;
		this.width = cfg.width || null;
		this.value = cfg.text || cfg.label || cfg.value || '';
		this.handler = cfg.handler || function() {};
		this.renderTo = cfg.renderTo || '';
		this.title = cfg.title || '';
		this.elmType = 'span';
		this.icon = cfg.icon || null;
		this.theme = cfg.theme || 'blue';
		this.type = cfg.type || 'normal';

		this.baseCls = this.type + '-button';
		this.blurCls = this.baseCls + ' ' + this.theme + '-' + this.baseCls;
		this.hoverCls = this.baseCls + '-hover' + ' ' + this.theme + '-' + this.baseCls + '-hover';
		this.errorCls = this.baseCls + '-error' + ' ' + this.theme + '-' + this.baseCls + '-error';
		this.disableCls = this.baseCls + '-disabled' + ' ' + this.theme + '-' + this.baseCls + '-disabled';

		this.selected = false;
		if ( Util.isDefined(cfg.selected) ) {
			this.selected = cfg.selected;
		}

		this.disabled = false;
		if ( Util.isDefined(cfg.disabled) ) {
			this.disabled = cfg.disabled;
		}

		this.createCnt();
		this.createElm();

		if ( !this.disabled ) {
			this.enable();
		} else {
			this.disable();
		}

		this.setValue(this.value);
		if ( this.icon ) {
			this.setIcon(this.theme + '-' + this.icon);
		}
	},

	createCnt: function() {
		this.cnt = Dom.create({
			tag: 'span',
			title: this.title
		});
		if ( this.renderTo ) {
			this.render(this.renderTo);
		}
	},

	createElm: function() {
		this.elm = Dom.create({
			tag: this.elmType,
			renderTo: this.cnt
		});
		if ( this.width ) {
			this.elm.style.width = this.width + 'px';
		}
		if ( this.height ) {
			this.elm.style.height = this.height + 'px';
		}
	},

	setIcon: function(icon) {
		$(this.elm).attr('class', icon);
	},

	setValue: function(val) {
		this.value = val;
		$(this.elm).html(val);
	},

	getValue: function() {
		return this.value;
	},

	addListener: function(eventName, handler) {
		var elm = this.elm;
		if ( eventName == 'click' ) {
			elm.onclick = handler;
		}
	},

	setHandler: function(handler) {
		var elm = this.elm;
		var btn = this;
		this.handler = handler;
		if ( !this.selected || !this.disabled ) {
			elm.onclick = function(e) {
				handler(btn);
				//prevent event propagation
				if (!e) var e = window.event;
				e.cancelBubble = true;
				if (e.stopPropagation) e.stopPropagation();
			}
		}
	},

	enable: function() {
		var btn = this;
		var cnt = this.cnt;
		var theme = this.theme;

		if ( !this.selected ) {
			$(cnt).attr('class', this.blurCls);
			cnt.onmouseover = function() {
				$(cnt).attr('class', btn.hoverCls);
/*				if ( elm.className != 'trigger-button-error' )
					elm.className = btnType + '-button-hover';*/
			}
			cnt.onmouseout = function() {
				$(cnt).attr('class', btn.blurCls);
/*				if ( elm.className != 'trigger-button-error' )
					elm.className = btnType + '-button';*/
			}
		} else {
			cnt.className = type + '-button-selected';
		}

		//todo: add all event listeners
		if ( this.handler ) {
			this.setHandler(this.handler);
/*			var handler = this.handler;
			elm.onclick = function(e) {
				handler();
				if (!e) var e = window.event;
				e.cancelBubble = true;
				if (e.stopPropagation) e.stopPropagation();
			}*/
		}
	},

	disable: function() {
		var btn = this;
		var cnt = this.cnt;
		$(cnt).attr('class', btn.disableCls);
		cnt.onclick = null;
		cnt.onmouseover = null;
		cnt.onmouseout = null;
	},

	render: function(renderTo) {
		Dom.add(this.cnt, Dom.get(renderTo));
	}

});

var CheckBox = Field.extend({

	init: function(cfg) {
		this.checked = false;
		if ( Util.isDefined(cfg.checked) ) {
			this.checked = cfg.checked;
		}
		this._super(cfg);
	},

	createElm: function() {
		this.elmCont = Dom.create({
			tag: 'span',
			cls: 'checkbox',
			renderTo: this.mainCont
		});
		this.elm = Dom.create({
			tag: 'checkbox',
			name: this.name,
			renderTo: this.elmCont
		});
		if ( this.text ) {
			alert('yes');
		}
	},

	render: function(renderTo) {
		this._super(renderTo);
		//because of the stupid ie
		this.elm.checked = this.checked;
	},

	enable: function() {
		var chb = this.elm;

		this.elmCont.onmouseover = function() {
			this.className = 'checkbox-hover';
		}

		this.elmCont.onmouseout = function() {
			this.className = 'checkbox';
		}

		this.elmCont.onclick = function() {
			if ( chb.checkboxChecked ) {
				chb.checkboxChecked = false;
			} else {
				if ( chb.checked ) {
					chb.checked = false;
				} else {
					chb.checked = true;
				}
			}
		}

		chb.onclick = function() {
			chb.checkboxChecked = true;
		}
	}

});

var ToggleButton = Button.extend({

	init: function(cfg) {
		cfg.height = 16;
		this._super(cfg);
		this.selectedCls = this.baseCls + '-selected' + ' ' + this.theme + '-' + this.baseCls + '-selected';
	},

	select: function() {
		this.selected = true;
		var cnt = this.cnt;
		var type = this.type;
		$(cnt).attr('class', this.selectedCls);
		cnt.onmouseover = null;
		cnt.onmouseout = null;
	},

	deselect: function() {
		this.selected = false;
		var btn = this;
		var cnt = this.cnt;
		var type = this.type;
		$(cnt).attr('class', btn.blurCls);
		cnt.onmouseover = function() {
			$(cnt).attr('class', btn.hoverCls);
/*			if ( cnt.className != 'trigger-button-error' )
				cnt.className = btnType + '-button-hover';*/
		}
		cnt.onmouseout = function() {
			$(cnt).attr('class', btn.blurCls);
/*			if ( cnt.className != 'trigger-button-error' )
				cnt.className = btnType + '-button';*/
		}
	},

	error: function() {
		$(this.cnt).attr('class', this.errorCls);
	}

});

function ListView(cfg) {

	this.create = function(cfg) {
		this.theme = cfg.theme || 'blue';
		this.itemsCont = Dom.create({
			tag: 'ul',
			cls: 'listview-container ' + this.theme + '-listview-container',
			renderTo: Dom.get(cfg.renderTo)
		});

		this.handler = cfg.handler || function() {};
		this.updateItems(cfg.items);

	}

	this.updateItems = function(items) {

		var listView = this;
		var itemsCont = this.itemsCont;

		var count;

		//remove old content
		while( itemsCont.hasChildNodes() ) {
			itemsCont.removeChild(itemsCont.firstChild);
		}

		for ( var i = 0; i < items.length; i++ ) {
			var item = items[i];
			var li = Dom.create('li');
			li.even = (i % 2 == 0);

			count = 0;
			while ( item.charAt(0) == '|' ) {
				count++;
				item = item.substr(1);
				li.style.paddingLeft = count * 25 + 'px';
			}

			li.innerHTML = item;

			if ( li.even ) {
				li.className = 'node-even';
			} else {
				li.className = 'node-odd';
			}

			li.onmouseover = function() {
				this.className = 'node-hover';
			}

			li.onmouseout = function() {
				var n = parseInt(this.id.split('-')[1]);
				if ( this.even ) {
					this.className = 'node-even';
				} else {
					this.className = 'node-odd';
				}
			}

			li.onclick = function() {
				listView.handler(this.innerHTML);
			}

			Dom.add(li, itemsCont);
		}
	}

	this.create(cfg);
}

var TextArea = Field.extend({

	init: function(cfg) {
		this.fieldType = 'textarea';
		cfg.height = cfg.height || 50;
		cfg.width = cfg.width || 248;
		this._super(cfg);
	}

});

var PlainField = Class.extend({

	init: function(cfg) {

		this.label = cfg.label || '';
		this.width = cfg.width || 198;
		this.allowBlank = true;
		this.visible = true;
		this.value = '';
		this.standAlone = true;

		this.expand = false;
		if ( Util.isDefined(cfg.expand) ) {
			this.expand = cfg.expand;
		}

		if ( Util.isDefined(cfg.visible) ) {
			this.visible = cfg.visible;
		}

		if ( cfg.text ) {
			this.text = cfg.text;
		}

		if ( cfg.value ) {
			this.setValue(cfg.value);
		}

		this.createMainCont(cfg);
		this.draw();
		this.createMsgCont();

	},

	draw: function() {
		var textCont = Dom.create({
			tag: 'div',
			text: this.value,
			renderTo: this.mainCont
		});
		textCont.style.paddingTop = '3px';
	},

	createMainCont: function(cfg) {
		this.mainCont = Dom.create({
			cls: 'plain-field',
			tag: 'span'
		});
		if ( cfg.renderTo ) {
			this.render(cfg.renderTo);
		}
	},

	createMsgCont: function() {
		if ( this.standAlone ) {
			this.msgCont = Dom.create({
				tag: 'span',
				cls: 'field-error',
				renderTo: this.mainCont
			});
		}
	},

	error: function(msg, elm) {
		var elm = this.elm;
		elm.className = this.fieldType + '-error';
		this.msgCont.innerHTML = msg;
	},

	render: function(renderTo) {
		Dom.add(this.mainCont, Dom.get(renderTo));
	},

	setValue: function(val) {
		this.value = val;
	},

	validate: function() {
		return true;
	}

});

var Delim = Class.extend({

	init: function(cfg) {
		this.expand = true;
		this.visible = true;

		if ( cfg.renderTo ) {
			this.render(cfg.renderTo);
		}
	},

	render: function(renderTo) {
		Dom.create({
			tag: 'div',
			cls: 'form-delim',
			renderTo: renderTo
		});
		Dom.create({
			tag: 'br',
			renderTo: renderTo
		});
	},

	validate: function() {
		return true;
	}

});

function FormView(cfg) {

	this.create = function(cfg) {

		this.ctrlConts = [];
		this.ctrlsByName = [];
		this.ctrlsByLabel = [];

		this.mainCont = Dom.create({
			tag: 'div',
			cls: 'form-view'
		});

		if ( cfg.renderTo ) {
			this.render(cfg.renderTo);
		}

		this.form = Dom.create({
			tag: 'form',
			renderTo: this.mainCont
		});
		this.form.action = cfg.action;
		this.form.method = cfg.method;
		this.form.name = cfg.name;

		if ( cfg.enctype ) {
			this.form.enctype = cfg.enctype;
// 			this.form.encoding = cfg.enctype;
		}

		this.items = cfg.items;

		var fvCont = Dom.create({
			tag: 'table',
			renderTo: this.form
		});

		fvCont.cellPadding = '1px';
		fvCont.cellSpacing = '0px';
		fvCont.width = '100%';
		fvCont.border = '0';

		var fvBody = Dom.create({
			tag: 'tbody',
			renderTo: fvCont
		});

		if ( cfg.label || cfg.message ) {
			var tr = Dom.create({
				tag: 'tr',
				renderTo: fvBody
			});
			var td = Dom.create({
				tag: 'td',
				renderTo: tr
			});
			td.colSpan = '2';

			if ( cfg.label ) {
				Dom.create({
					tag: 'h3',
					cls: 'form-label',
					text: cfg.label,
					renderTo: td
				});
			}
			new Delim({renderTo: td});

			if ( cfg.message ) {
				Dom.create({
					tag: 'div',
					cls: 'form-message',
					text: cfg.message,
					renderTo: td
				});
				new Delim({renderTo: td});

			}

		}

		for ( var i = 0; i < this.items.length; i++ ) {

			var ctrl = this.items[i];
			if ( ctrl.name )
				this.ctrlsByName[ctrl.name] = ctrl;
			if ( ctrl.label )
				this.ctrlsByLabel[ctrl.label] = ctrl;

			var tr = Dom.create({
				tag: 'tr',
				renderTo: fvBody
			});

			if ( ctrl.name ) {
				this.ctrlConts[ctrl.name] = tr;
			}

			if ( !ctrl.visible ) {
				this.hide(ctrl.name);
			}


			if ( ctrl.expand ) {

				var td = Dom.create({
					tag: 'td',
					renderTo: tr
				});
				td.colSpan = '2';
				td.align = 'center';
				ctrl.render(td);

			} else {

				var lbl = ctrl.label;
				if ( lbl != '' ) {
					lbl += ':';
				}

				var td1 = Dom.create({
					tag: 'td',
					cls: 'form-view-labels',
					text: lbl,
					renderTo: tr
				});
				var td2 = Dom.create({
					tag: 'td',
					renderTo: tr
				});
				td2.style.paddingRight = '20px';

				ctrl.render(td2);

			}
		}

		if ( cfg.buttons ) {
			var tr = Dom.create({
				tag: 'tr',
				renderTo: fvBody
			});
			var td = Dom.create({
				tag: 'td',
				renderTo: tr
			});
			td.colSpan = '2';
			new Delim({renderTo: td});

			var tr = Dom.create({
				tag: 'tr',
				renderTo: fvBody
			});
			Dom.create({
				tag: 'td',
				renderTo: tr
			});
			var td = Dom.create({
				tag: 'td',
				renderTo: tr
			});

			var btnContCls = 'button-container';
			for ( var i = 0; i < cfg.buttons.length; i++ ) {

				var btn = cfg.buttons[i];
				if ( btn.disabled ) {
					btnContCls = 'disabled-button-container';
				}

				var btnCont = Dom.create({
					tag: 'span',
					cls: btnContCls,
					renderTo: td
				});

				btn.render(btnCont);

			}
		}
	}

	this.getFieldByName = function(fldName) {
		return this.ctrlsByName[fldName];
	}

	this.getFieldByLabel = function(fldLbl) {
		return this.ctrlsByLabel[fldLbl];
	}

	this.render = function(renderTo) {
		Dom.add(this.mainCont, Dom.get(renderTo));
	}

	this.getForm = function() {
		return this.form;
	}

	this.validate = function() {
		this.isValid = true;
		for ( var i = 0; i < this.items.length; i++ ) {

			var ctrl = this.items[i];
			ctrl.validate();
			this.isValid =  ctrl.validate() && this.isValid;

		}
		return this.isValid;
	}

	this.addHiddenValue = function(name, value) {
		var hiddenField = Dom.create({
			tag: 'input',
			type: 'hidden',
			value: value,
			name: name,
			renderTo: this.form
		});
	}

	this.hide = function(ctrlName) {
		this.ctrlConts[ctrlName].style.display = 'none';
	}

	this.show = function(ctrlName) {
		if (navigator.appName.indexOf('MSIE')==-1 && navigator.appName.indexOf('Internet Explorer')==-1)
			this.ctrlConts[ctrlName].style.display = 'table-row';
		else
			this.ctrlConts[ctrlName].style.display = 'block';
	}

	this.create(cfg);
}

