
Ext.override(Ext.form.DateField, {
	format : "M/d/yy",

	parseDate : function(value){
		if(!value || value instanceof Date){
			return value;
		}
		return Date.parse(value);
	},

	formatDate : function(date){
		d = (!date || !(date instanceof Date)) ? date : date.toString(this.format);
		return d;
	},

	// private
	validateValue : function(value){
		value = this.formatDate(value);
		if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
			return false;
		}
		if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
			 return true;
		}
		var svalue = value;
		value = this.parseDate(value);
		if(!value){
			this.markInvalid(String.format(this.invalidText, svalue, this.format));
			return false;
		}
		var time = value.getTime();
		if(this.minValue && time < this.minValue.getTime()){
			this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
			return false;
		}
		if(this.maxValue && time > this.maxValue.getTime()){
			this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
			return false;
		}
		if(this.disabledDays){
			var day = value.getDay();
			for(var i = 0; i < this.disabledDays.length; i++) {
				if(day === this.disabledDays[i]){
					this.markInvalid(this.disabledDaysText);
					return false;
				}
			}
		}
		var fvalue = this.formatDate(value);
		if(this.disabledDatesRE && this.disabledDatesRE.test(fvalue)){
			this.markInvalid(String.format(this.disabledDatesText, fvalue));
			return false;
		}
		return true;
	},
	

	setValue : function(date){
		var d = this.formatDate(this.parseDate(date));
		Ext.form.DateField.superclass.setValue.call(this, d);
	}	

});

Ext.override(Ext.DatePicker, {
	format : "M/d/yy",

	/**
	* Sets the value of the date field
	* @param {Date} value The date to set
	*/
	setValue : function(value){
		//debugger;
		var old = this.value;
		this.value = value.clone().clearTime();
		if(this.el){
			this.update(this.value);
		}
	},

	// private
	onRender : function(container, position){
		var m = [
			 '<table cellspacing="0">',
				'<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
				'<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
		var dn = this.dayNames;
		for(var i = 0; i < 7; i++){
			var d = this.startDay+i;
			if(d > 6){
				d = d-7;
			}
			/// Pull the one character strings directly from Date.CultureInfo.firstLetterDayNames
			m.push("<th><span>", Date.CultureInfo.firstLetterDayNames[d], "</span></th>");
			//m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
		}
		m[m.length] = "</tr></thead><tbody><tr>";
		for(var i = 0; i < 42; i++) {
			if(i % 7 == 0 && i != 0){
				m[m.length] = "</tr><tr>";
			}
			m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
		}
		m.push('</tr></tbody></table></td></tr>',
				this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
				'</table><div class="x-date-mp"></div>');

		var el = document.createElement("div");
		el.className = "x-date-picker";
		el.innerHTML = m.join("");

		container.dom.insertBefore(el, position);

		this.el = Ext.get(el);
		this.eventEl = Ext.get(el.firstChild);

		this.leftClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
			handler: this.showPrevMonth,
			scope: this,
			preventDefault:true,
			stopDefault:true
		});

		this.rightClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
			handler: this.showNextMonth,
			scope: this,
			preventDefault:true,
			stopDefault:true
		});

		this.eventEl.on("mousewheel", this.handleMouseWheel,  this);

		this.monthPicker = this.el.down('div.x-date-mp');
		this.monthPicker.enableDisplayMode('block');

		var kn = new Ext.KeyNav(this.eventEl, {
			"left" : function(e){
				e.ctrlKey ?
					this.showPrevMonth() :
					//this.update(this.activeDate.add("d", -1));
					this.update(this.activeDate.clone().addDays(-1));
			},

			"right" : function(e){
				e.ctrlKey ?
					this.showNextMonth() :
					//this.update(this.activeDate.add("d", 1));
					this.update(this.activeDate.clone().addDays(1));
			},

			"up" : function(e){
				e.ctrlKey ?
					this.showNextYear() :
					//this.update(this.activeDate.add("d", -7));
					this.update(this.activeDate.clone().addDays(-7));
			},

			"down" : function(e){
				e.ctrlKey ?
					this.showPrevYear() :
					//this.update(this.activeDate.add("d", 7));
					this.update(this.activeDate.clone().addDays(7));
			},

			"pageUp" : function(e){
				this.showNextMonth();
			},

			"pageDown" : function(e){
				this.showPrevMonth();
			},

			"enter" : function(e){
				e.stopPropagation();
				return true;
			},

			scope : this
		});

		this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});

		this.el.unselectable();

		this.cells = this.el.select("table.x-date-inner tbody td");
		this.textNodes = this.el.query("table.x-date-inner tbody span");

		this.mbtn = new Ext.Button({
			text: "&#160;",
			tooltip: this.monthYearText,
			renderTo: this.el.child("td.x-date-middle", true)
		});

		this.mbtn.on('click', this.showMonthPicker, this);
		this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

		if(this.showToday){
			this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
			//var today = (new Date()).dateFormat(this.format);
			var today = Date.today().toString(this.format);
			this.todayBtn = new Ext.Button({
				renderTo: this.el.child("td.x-date-bottom", true),
				text: String.format(this.todayText, today),
				tooltip: String.format(this.todayTip, today),
				handler: this.selectToday,
				scope: this
			});
		}

		if(Ext.isIE){
			this.el.repaint();
		}
		this.update(this.value);
	},

	// private
	showPrevMonth : function(e){
		/// other options include...
		/// .add(1).month()
		/// .add({months: 1})
		/// ... but .addMonths() has the fastest performance
		this.update(this.activeDate.clone().addMonths(-1));
		///this.update(this.activeDate.add("mo", -1));
	},

	// private
	showNextMonth : function(e){
		this.update(this.activeDate.clone().addMonths(1));
		///this.update(this.activeDate.add("mo", 1));
	},

	// private
	showPrevYear : function(){
		/// other options include...
		/// .add(1).year()
		/// .add({years: 1})
		/// ... but .addYears() has the fastest performance
		this.update(this.activeDate.clone().addYears(-1));
		///this.update(this.activeDate.add("y", -1));
	},

	// private
	showNextYear : function(){
		this.update(this.activeDate.clone().addYears(1));
		///this.update(this.activeDate.add("y", 1));
	},

	// private
	selectToday : function(){
		/// Same as Date.today(), but shorter.
		this.setValue(Date.today());
		///this.setValue(new Date().clearTime());

		this.fireEvent("select", this, this.value);
	},


	// private
	update : function(date, forceRefresh){
		
		var vd = this.activeDate;
		//this.activeDate = date;
		this.activeDate = date.clone();
		if(!forceRefresh && vd && this.el){
			var t = date.getTime();
			if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
				this.cells.removeClass("x-date-selected");
				this.cells.each(function(c){
				   if(c.dom.firstChild.dateValue == t){
					   c.addClass("x-date-selected");
					   setTimeout(function(){
							try{c.dom.firstChild.focus();}catch(e){}
					   }, 50);
					   return false;
				   }
				});
				return;
			}
		}
		var days = date.getDaysInMonth();
		//var firstOfMonth = date.getFirstDateOfMonth();
		var firstOfMonth = date.clone().moveToFirstDayOfMonth();
		var startingPos = firstOfMonth.getDay()-this.startDay;

		if(startingPos <= this.startDay){
			startingPos += 7;
		}

		//var pm = date.add("mo", -1);
		var pm = date.clone().addMonths(-1);
		var prevStart = pm.getDaysInMonth()-startingPos;

		var cells = this.cells.elements;
		var textEls = this.textNodes;
		days += startingPos;

		// convert everything to numbers so it's fast
		var day = 86400000;
		var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
		//var today = new Date().clearTime().getTime();
		var today = Date.today().getTime();
		var sel = date.clearTime().getTime();
		var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
		var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
		var ddMatch = this.disabledDatesRE;
		var ddText = this.disabledDatesText;
		var ddays = this.disabledDays ? this.disabledDays.join("") : false;
		var ddaysText = this.disabledDaysText;
		var format = this.format;

		if(this.showToday){
			var td = new Date().clearTime();
			var disable = (td < min || td > max ||
				//(ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
				(ddMatch && format && ddMatch.test(td.toString(format))) ||
				(ddays && ddays.indexOf(td.getDay()) != -1));

			this.todayBtn.setDisabled(disable);
			this.todayKeyListener[disable ? 'disable' : 'enable']();
		}

		var setCellClass = function(cal, cell){
			cell.title = "";
			var t = d.getTime();
			cell.firstChild.dateValue = t;
			if(t == today){
				cell.className += " x-date-today";
				cell.title = cal.todayText;
			}
			if(t == sel){
				cell.className += " x-date-selected";
				setTimeout(function(){
					try{cell.firstChild.focus();}catch(e){}
				}, 50);
			}
			// disabling
			if(t < min) {
				cell.className = " x-date-disabled";
				cell.title = cal.minText;
				return;
			}
			if(t > max) {
				cell.className = " x-date-disabled";
				cell.title = cal.maxText;
				return;
			}
			if(ddays){
				if(ddays.indexOf(d.getDay()) != -1){
					cell.title = ddaysText;
					cell.className = " x-date-disabled";
				}
			}
			if(ddMatch && format){
				//var fvalue = d.dateFormat(format);
				var fvalue = d.toString(format);
				if(ddMatch.test(fvalue)){
					cell.title = ddText.replace("%0", fvalue);
					cell.className = " x-date-disabled";
				}
			}
		};

		var i = 0;
		for(; i < startingPos; i++) {
			textEls[i].innerHTML = (++prevStart);
			d.setDate(d.getDate()+1);
			cells[i].className = "x-date-prevday";
			setCellClass(this, cells[i]);
		}
		for(; i < days; i++){
			var intDay = i - startingPos + 1;
			textEls[i].innerHTML = (intDay);
			d.setDate(d.getDate()+1);
			cells[i].className = "x-date-active";
			setCellClass(this, cells[i]);
		}
		var extraDays = 0;
		for(; i < 42; i++) {
			 textEls[i].innerHTML = (++extraDays);
			 d.setDate(d.getDate()+1);
			 cells[i].className = "x-date-nextday";
			 setCellClass(this, cells[i]);
		}

		this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());

		if(!this.internalRender){
			var main = this.el.dom.firstChild;
			var w = main.offsetWidth;
			this.el.setWidth(w + this.el.getBorderWidth("lr"));
			Ext.fly(main).setWidth(w);
			this.internalRender = true;
			// opera does not respect the auto grow header center column
			// then, after it gets a width opera refuses to recalculate
			// without a second pass
			if(Ext.isOpera && !this.secondPass){
				main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
				this.secondPass = true;
				this.update.defer(10, this, [date]);
			}
		}
	}


});
