ja.Calendar = Class.create({

	classNames: {
		days: ['sun','mon','tue','wed','thu','fri','sat'],
		cols: ['col1','col2','col3','col4','col5','col6','col7'],
		prevmonth: 'prevmonth',
		nextmonth: 'nextmonth',
		selected: 'selected',
		holiday: 'holiday'
	},
	
	initialize: function(cfg) {
		cfg = cfg || {}
		if (cfg.classNames) Object.extend(this.classNames,cfg.classNames)
		this.locale = ja.i18n.getLocale(cfg.locale || 'c')
	},
	
	styleHeader: function(th,weekday) {
		th.addClassName(this.classNames.cols[(weekday + 7 - this.locale.weekstartday) % 7])
		th.addClassName(this.classNames.days[weekday])
		th.update(this.locale.days1[weekday].toTitleCase())
	},

	styleDay: function(td,date,dateMonth,selected) {
		td.addClassName(this.classNames.cols[(date.getDay() + 7 - this.locale.weekstartday) % 7])
		td.addClassName(this.classNames.days[date.getDay()])
		if (dateMonth.getMonth() < date.getMonth()) td.addClassName(this.classNames.prevmonth)
		if (dateMonth.getMonth() > date.getMonth()) td.addClassName(this.classNames.nextmonth)
		if (date.sameDay(selected)) { td.addClassName(this.classNames.selected) }
		td.update(date.format('d',this.locale))
	},
	
	styleHolyday: function(td,date,dateMonth,selected,holiday) {
		td.addClassName(this.classNames.holiday)
		td.title = holiday.desc
	},

	_td: function(td,date,dateMonth,selected,styler) {
		this.styleDay(td,date,dateMonth,selected)
		if (styler.styleDay) styler.styleDay.call(this,td,date,dateMonth,selected)
		this.locale.holidays.each(function(h) {
			if (h.condition(date)){
				this.styleHolyday(td,date,dateMonth,selected,h)
				if (styler.styleHolyday) styler.styleHolyday.call(this,td,date,dateMonth,selected,h)
			}
		},this)
	},

	render: function(container,date,selected,styler) {
		styler = styler || {}
		var table = new Element('table')
		var thead = new Element('thead')
		var tbody = new Element('tbody')
		table.insert(thead).insert(tbody)
		
		{
			var tr = new Element('tr')
			thead.insert(tr)
			;(7).times(function(n) {
				var th = new Element('th')
				tr.insert(th)
				this.styleHeader(th,(this.locale.weekstartday + n) % 7)
				if (styler.styleHeader) styler.styleHeader.call(this,th,(this.locale.weekstartday + n) % 7)
			},this)
		}
		
		var first = date.clone()
		first.setDate(1)
		first.setDate(this.locale.weekstartday - first.getDay() +1)

		var d = first.clone()
		for (var r = 0; r < 6; r++) {
			var tr = new Element('tr')
			tbody.insert(tr)
			for (var c = 0; c < 7; c++) {
				var td = new Element('td')
				tr.insert(td)
				this._td(td,d,date,selected,styler)
				d = d.nextDay()
			}
		}

		$(container).update(table)
	}
})

ja.DatePicker = Class.create({
	button: null,
	calendar: null,
	selected: Date.today(),
	displayed: Date.today(),
	elements: {
		widget:    null,
		title:     null,
		prevMonth: null,
		nextMonth: null,
		close:     null,
		calendar:  null
	},
	offset: {
		left: 0,
		top: 0
	},
	
	initialize: function (button,input,cfg) {
		cfg = cfg || {}
		this.button = $(button)
		this.input = $(input)
		this.calendar = cfg.calendar || new ja.Calendar()
		this.offset = {left:cfg.offsetLeft||0,top:cfg.offsetTop||0}
		
		this.button.observe('click',function(event){
			if (this.elements.widget.visible()) this.hide()
			else this.show()
		}.bind(this))
		this.input.observe('focus',function(event){
			this.hide()
		}.bind(this))
		
		this.elements = {
			container: new Element('div',{'style':'position:relative;'}),
			widget:    new Element('div',{'class':'calendar-widget'}),
			title:     new Element('div',{'class':'calendar-widget-title'}),
			prevMonth: new Element('div',{'class':'calendar-widget-prevMonth'}),
			nextMonth: new Element('div',{'class':'calendar-widget-nextMonth'}),
			close:     new Element('div',{'class':'calendar-widget-close'}),
			calendar:  new Element('div',{'class':'calendar-widget-calendar'})
		}
		with (this.elements) {
			widget.insert(close)
			      .insert(prevMonth)
			      .insert(nextMonth)
			      .insert(title)
			      .insert(calendar)
			prevMonth.update('&lt;')
			nextMonth.update('&gt;')
			close.update('x')
			
			container.observe('click', function(event){ Event.stop(event) })
			prevMonth.observe('click',function(event){ this.refresh(this.displayed.prevMonth()) }.bind(this))
			nextMonth.observe('click',function(event){ this.refresh(this.displayed.nextMonth()) }.bind(this))
		}
		button.insert(this.elements.container)
		this.elements.container.insert(this.elements.widget)
		this.elements.widget.absolutize().hide()
	},
	refresh: function(date) {
		this.displayed = date || this.selected
		this.elements.title.update(this.displayed.format('Mmmm yyyy'))
		var self = this
		this.calendar.render(this.elements.calendar,this.displayed,this.selected,{
			styleDay: function(td,date,dateMonth,selected) {
				td.observe('click',function(event){ self.select(date) })
			}
		})
		var w = this.elements.widget
		w.setStyle({top:'20px',right:'-5px'})
		w.show()
		var l = w.viewportOffset()[0]
		if (l < 0) w.setStyle({'right':(new Number(w.getStyle('right').replace('px','')) + l) + 'px'})
	},
	hide: function() { this.elements.widget.hide() },
	select: function(date) {
		this.hide()
		self.selected = date
		if (this.input) this.input.value = date.format()
	},
	show: function() {
		var d = Date.parse(this.input.value,ja.i18n.getSystemLocale().formats.parseDate)
		if (isNaN(d)) { this.input.value = ''; d = Date.today() }
		else this.selected = d
		this.refresh()
	}
	
})

