/*jslint laxbreak: true, eqeqeq: true, browser: true, undef: true */
/*extern $, Class, Options, Element, Request */
/*extern Uplayer, trace */
/*global DR */

// Create namespaces
if (!DR) { DR = {}; }
if (!DR.Ung ) { DR.Ung = {}; }
if (!DR.Ung.Input ) { DR.Ung.Input = {}; }

DR.Ung.Input.DatePicker = new Class({
	Implements: Options
	,options: {
		show_time: false
		,outputDateFormat: "dd-MM-yyyy"
		,outputTimeFormat: "HH:mm"
		,inputDateFormat: "dd-MM-yyyy"
		,inputTimeFormat: "HH:mm"
		,validateDate: function(date){return true;}
	}
	,parent: null
	,getDatePickerString: function(){ 
		var timeString = "";
		if(this.options.show_time){
			timeString = '<tfoot id="timePicker"><tr><td class="hour" colspan="4"><div class="hourWrap"><a id="dp_addHour" href="#">+</a><a id="dp_subHour" href="#">-</a><input id="dp_hour" type="text" value="{hour}" readonly="readonly" /></div></td><td class="minute" colspan="4"><div class="minuteWrap"><input id="dp_minute" type="text" value="{minute}" readonly="readonly" /><a id="dp_addMinute" href="#">+</a><a id="dp_subMinute" href="#">-</a></div></td></tr></tfoot>';
		}
		var dpstring =
			"<table>\n" +
			"	<caption><span><a id=\"dp_prevmonth\" href=\"#\">&lt;</a></span><span id=\"dp_month\">{month}</span> <span id=\"dp_year\">{year}</span><span><a id=\"dp_nextmonth\" href=\"#\">&gt;</a></span></caption>\n" +
			"   <col class=\"weeknumber\" />\n" +
			"   <col class=\"weekday\" span=\"5\" />\n" +
			"   <col class=\"weekend\" span=\"2\" />\n" +
			"   <thead>\n" +
			"	    <tr><th class=\"weeknumber\">UGE</th><th>M</th><th>T</th><th>O</th><th>T</th><th>F</th><th>L</th><th>S</th></tr>\n" +
			"   </thead>\n" +
				timeString +
			"   <tbody>\n" +
			"	    <tr id=\"dp_week1\">\n" +
			"		    <td class=\"weeknumber\">{week_1}</td>{dp_week1_1}{dp_week1_2}{dp_week1_3}{dp_week1_4}{dp_week1_5}{dp_week1_6}{dp_week1_7}\n" +
			"	    </tr>" +
			"	    <tr id=\"dp_week2\">\n" +
			"	    	<td class=\"weeknumber\">{week_2}</td>{dp_week2_1}{dp_week2_2}{dp_week2_3}{dp_week2_4}{dp_week2_5}{dp_week2_6}{dp_week2_7}\n" +
			"	    </tr>\n" +
			"	    <tr id=\"dp_week3\">\n" +
			"	    	<td class=\"weeknumber\">{week_3}</td>{dp_week3_1}{dp_week3_2}{dp_week3_3}{dp_week3_4}{dp_week3_5}{dp_week3_6}{dp_week3_7}\n" +
			"	    </tr>\n" +
			"	    <tr id=\"dp_week4\">\n" +
			"	    	<td class=\"weeknumber\">{week_4}</td>{dp_week4_1}{dp_week4_2}{dp_week4_3}{dp_week4_4}{dp_week4_5}{dp_week4_6}{dp_week4_7}\n" +
			"	    </tr>\n" +
			"	    <tr id=\"dp_week5\">\n" +
			"	    	<td class=\"weeknumber\">{week_5}</td>{dp_week5_1}{dp_week5_2}{dp_week5_3}{dp_week5_4}{dp_week5_5}{dp_week5_6}{dp_week5_7}\n" +
			"	    </tr>\n" +
			"	    <tr id=\"dp_week6\">\n" +
			"	    	<td class=\"weeknumber\">{week_6}</td>{dp_week6_1}{dp_week6_2}{dp_week6_3}{dp_week6_4}{dp_week6_5}{dp_week6_6}{dp_week6_7}\n" +
			"	    </tr>\n" +
			"   </tbody>\n" +
			"</table>\n";
		return dpstring;
	}
	,initialize: function(element, options){
		this.setOptions(options);
		
		this.parent = element;
		this.currentDate = new Date();
		this.element = null;
		
		this.bound = {
			updateElement: this.updateElement.bind(this)
			,selectDate: this.selectDate.bind(this)
			,selectTime: this.selectTime.bind(this)
			,show: this.show.bind(this)
			,hide: this.hide.bind(this)
		};
		
		$(element).addEvent('focus', function(e){
			e.stop();
            if ($(e.target).hasClass('disabled')) {
                $(e.target).blur();
                return;
            }

			var newDate = new Date(Date.parse($(e.target).value));
    		if(this.options.validateDate(newDate)){
    		    this.currentDate = newDate;
    			this.bound.updateElement(this.currentDate);
    		}
			this.bound.show();
		}.bindWithEvent(this));
		$(element).addEvent('click', function(e){e.stop();});
		$(element).getParent('body').addEvent('click', function(e){
			//e.stop();
			if(this.element !== null){
				var inputDate = Date.parseExact(this.parent.get('value'), this.options.inputDateFormat + (this.options.show_time? " " + this.options.inputTimeFormat:""));
				if(inputDate !== null && Date.compare(inputDate, this.currentDate)!==0) {
					this.currentDate = inputDate;
				}
				this.parent.set('value', this.currentDate.toString(this.options.outputDateFormat + (this.options.show_time ? " " + this.options.outputTimeFormat : "")));
				this.bound.hide();
				this.element.destroy();
				this.element = null;
			}
		}.bindWithEvent(this));
	}
	,updateElement: function(date){
		this.currentDate = date.clone();
		var dateObj = {
			month: date.toString('MMMM').capitalize()
			,year: date.toString('yyyy')
			,hour: date.toString('HH')
			,minute: date.toString('mm')
		};
		for(var i = 1; i <= 6; i++){
			dateObj['week_' + i] = date.clone().setDay(1).addWeeks(i - 1).getWeek();
			for(var j = 1; j <= 7; j++){
				var day = date.clone().setDay(1).addWeeks(i - 1).setDayOfWeek(j);
				var finalString = "<td id=\"dp_week" + i + "_" + j + "\" class=\"";
				if(date.getMonth() !== day.getMonth()){
					finalString += "not_in_month";
				} else if(date.getDate() === day.getDate()) {
					finalString += "selected";
				}
				finalString += "\"><a href=\"#\" rel=\"" + day.toString('yyyy-MM-dd') +"\">" + day.getDate() + "</a></td>";
				dateObj['dp_week' + i + '_' + j] = finalString;
			}
		}
		var el = new Element('div', {html: this.getDatePickerString().substitute(dateObj), 'id': 'calendar', 'events':{'click':function(e){e.stop();}}});
		
		if(this.element === null){
			el.inject(this.parent, 'after');
		}
		else {
			el.replaces(this.element);
		}
		this.element = el;
		el.getElement('#dp_prevmonth').addEvent('click', function(){this.bound.selectDate(this.currentDate.addMonths(-1));}.bind(this));
		el.getElement('#dp_nextmonth').addEvent('click', function(){this.bound.selectDate(this.currentDate.addMonths(1));}.bind(this));
		for(i = 1; i <= 6; i++){
			for(j = 1; j <= 7; j++){
				var element = el.getElement('#dp_week' + i + '_' + j);
				var selectedD = Date.parseExact(element.getElement('a').get('rel'), 'yyyy-MM-dd');
				element.addEvent('click', function(d){
					return function(){
						this.bound.selectDate(d);
					};
				}(selectedD).bind(this));
			}
		}
		if(this.options.show_time){
			el.getElement('#dp_addHour').addEvent('click', function(){
				this.bound.selectDate(this.currentDate.clone().addHours(1));
			}.bind(this));
			el.getElement('#dp_subHour').addEvent('click', function(){
				this.bound.selectDate(this.currentDate.clone().addHours(-1));
			}.bind(this));
			
			el.getElement('#dp_addMinute').addEvent('click', function(){
				this.bound.selectDate(this.currentDate.clone().addMinutes(1));
			}.bind(this));
			el.getElement('#dp_subMinute').addEvent('click', function(){
				this.bound.selectDate(this.currentDate.clone().addMinutes(-1));
			}.bind(this));
		}
	}
	,selectDate: function(date){
		if(this.options.validateDate(date)){
    		this.updateElement(date);
    		this.parent.set('value', date.toString(this.options.outputDateFormat + (this.options.show_time ? " " + this.options.outputTimeFormat : "")));
            this.parent.fireEvent('change');
		}
	}
	,selectTime: function(hour, minute){
		var newDate = this.currentDate.clone();
		newDate.setHours(hour);
		newDate.setMinutes(minute);
		if(this.options.validateDate(newDate)){
    		this.updateElement(newDate);
    		this.parent.set('value', newDate.toString(this.options.outputDateFormat + (this.options.show_time ? " " + this.options.outputTimeFormat : "")));
            this.parent.fireEvent('change');
		}
	}
	,show: function(){
	}
	,hide: function(){
	}
});


/* Class: DR.Ung.Input.Cliprater
 *      Input enhancement and ajaxification of the cliprating control (the five stars).
 *
 * Arguments:
 *      el: [mixed] element (or element id) of the form for the cliprater
 */
DR.Ung.Input.Cliprater = new Class({
    initialize: function (el) {
        var buttons = $(el).getElements('button');

        // get current rating
        this.currentRate = buttons
            .filter(function (x) { return x.get('class').match(/full/); })
            .map(function (x) { return x.get('value'); })
            .max();

        // url to post to
        this.url = $(el).getElement('form').get('action');

        buttons.addEvents({
            mouseenter: this.mouseenter.bindWithEvent(this)
            ,mouseleave: this.mouseleave.bindWithEvent(this)
            ,click: this.click.bindWithEvent(this)
        });
    }
    ,mouseenter: function (e) {
        clearTimeout(this.timer);

        var button = $(e.target);
        var rate = button.get('value');
        var buttons =  button.getParent('ol').getElements('button');

        this.clearRating(buttons);
        this.setRating(rate, buttons);
    }
    ,mouseleave: function (e) {
        var buttons =  $(e.target).getParent('ol').getElements('button');
        this.timer = function () {
            this.clearRating(buttons);
            this.setRating(this.currentRate, buttons);
        }.delay(500, this);
    }
    ,click: function (e) {
        e.target.blur();
        e.stop();        
        var button = $(e.target);
        button.getParent('ol').fade('hide');
        var rate = button.get('value');
        var buttons =  button.getParent('ol').getElements('button');
        var request = new Request.JSON({
            url: this.url
            ,onComplete: function (response) {
                // update currentRating with the new current rating
                $$('#stats .currentRating span').set('text', response.rate);
                this.currentRate = rate;
                button.getParent('ol').fade('in');
            }.bind(this)
        }).post({'rate': rate});
    }
    ,clearRating: function (buttons) {
        buttons
            .forEach( function (x) { x.set('class', x.get('class').replace('full', 'empty')); });
    }
    ,setRating: function (rate, buttons) {
        buttons
            .filter(function (x) { return x.get('value') <= rate; })
            .forEach( function (x) { x.set('class', x.get('class').replace('empty', 'full')); });
    }
});


/* Class: DR.Ung.Input.Resource
 *      
 */
DR.Ung.Input.Resource = new Class({
    Extends: Autocompleter
    
    ,options: {
        markQuery: false
        ,delay: 400
        
        ,statusElementSelector: null
        ,statusSuccessClass: 'ok'
        ,statusFailClass: 'notok'
        
        ,urlRegex: '(http|rtmp)'
    }
    
    ,query: function() {
        if (this.baseUrlRE.test(this.queryValue) ||
            this.urlLikeRE.test(this.queryValue))
        {
            this.testValue();
            this.update(null);
        }
        else {
            this.clearStatus();
            this.update([this.baseUrl.substitute([this.queryValue])]);
        }
    }
    
    ,initialize: function(el, options){
        this.parent(el, options);
        
        this.statusElement = this.options.statusElementSelector !== null ? $$(this.options.statusElementSelector) : this.element;
        
        if(this.element.retrieve('baseUrl') == undefined){
            this.baseUrl = $(el).get('src');
            this.element.store('baseUrl', this.baseUrl);
            //this.observer.setValue('');
        }
        
        this.baseUrlRE = new RegExp(this.baseUrl.replace('.','\\.').substitute(['(.+)']));
        this.urlLikeRE = new RegExp(this.options.urlRegex);
        this.httpRE = new RegExp('http://');
        
        this.addEvent('onSelection', this.testValue.bind(this));
        
        this.element.getParent('form').addEvent('reset', (function(){
            (function(){
                this.observer.setValue('');
                this.clearStatus();
            }).delay(1, this);
        }).bind(this));
        
        this.testValue();
    }
    ,testValue: function() {
        if(this.httpRE.test(this.observer.value)){
            var url = this.element.get('value');
            var xhr = new Request({
                url: url
                ,method: 'get'
            });
            xhr.addEvent('onFailure', this.setStatus.bind(this, false));
            xhr.addEvent('onSuccess', this.setStatus.bind(this, true));
            xhr.send();
        }
    }
    ,setStatus: function(success){
        var removed =  success ? this.options.statusFailClass : this.options.statusSuccessClass;
        var added   = !success ? this.options.statusFailClass : this.options.statusSuccessClass;
        this.statusElement.removeClass(removed);
        this.statusElement.addClass(added);
        
        if(success && this.baseUrlRE.test(this.element.get('value'))){
            this.fireEvent('onNewBaseUrl');
        }
    }
    ,clearStatus: function(){
        this.statusElement.removeClass(this.options.statusFailClass);
        this.statusElement.removeClass(this.options.statusSuccessClass);
    }
});

/* Class: DR.Ung.Input.Selector
 *
 *
 */
DR.Ung.Input.Selector = new Class({
    initialize: function(el, autocompleter, autoCompleterOptions){
        this.element = $(el);
        this.delimiter = this.element.get('value')[0];
        this.items = this.element.get('value').substring(1).split(new RegExp('\\s*'+ this.delimiter +'\\s*'));
        this.items = this.items.erase("");
        this.build();
        
        if(this.element.get('src') != undefined){
            var autoCompleter = autocompleter || Autocompleter.Request.JSON;
            var options = autoCompleterOptions || {'ajaxOptions': {'method':'get'}};
            this.completer = new autoCompleter(this.element, this.element.get('src'), options);
            this.completer.addEvent('onSelection',
                (function (element, selected, value, input) {
                    if(!this.items.contains(value)){
                        this.items.push(item);
                        this.addItem(value);
                    }
                }).bind(this)
            );
        }
    }
    ,build: function(){
        var newHtml = "" + 
            "<legend>{5}</legend>"+
            "<div class=\"list-editor cols\">"+
            "<div class=\"col\">"+
            "<label for=\"{0}-input\">{1}</label>"+
            "<input type=\"hidden\" name=\"{0}\" id=\"{0}\" />"+
            "<input type=\"text\" name=\"{0}-input\" id=\"{0}-input\" src=\"{3}\" />"+
            "<button class=\"add\">tilf&oslash;j</button>"+
            "<span class=\"field-help\">{2}</span>"+
            "</div>"+
            "<div class=\"col\">"+
            "<label>Nuv&aelig;rrende:</label>"+
            "<ol class=\"list-editor-items\"></ol>"+
            "</div>"+
            "</div>"+
            "";
        this.parent = this.element.getParent('fieldset');
        var strings = [this.element.get('name'),
                       this.parent.getElement('label[for='+this.element.get('id')+']').get('text'),
                       this.parent.getElement('span.field-help').get('html'),
                       this.element.get('src'),
                       this.parent.getElement('legend').get('text')];
        this.parent.set('html', newHtml.substitute(strings));
        this.element = this.parent.getElement('input[type=text]');
        this.element.addEvent('keypress', (function(e) {
            if(e.key === this.delimiter){
                var item = this.element.get('value').trim().replace(this.delimiter,'');
                if(item.trim() !== '' && !this.items.contains(item)){
                    this.items.push(item);
                    this.addItem(item);
                } else {
                    this.element.set('value','');
                }
                e.stop();
            }
        }).bind(this));
        this.items.each(this.addItem.bind(this));
        this.parent.getElement('button').addEvent('click', (function(e){
            e.stop();
            e.target.blur();
            var item = this.element.get('value');
            if(item.trim() !== '' && !this.items.contains(item)){
                this.items.push(item);
                this.addItem(this.element.get('value'));
            }
        }).bind(this));
    }
    ,removeItem: function(item){
        this.items.erase(item);
        this.parent.getElement('input[type=hidden]').set('value', this.delimiter + this.items.join(this.delimiter));
    }
    ,addItem: function(item){
        var itemElement = new Element('li');
        var itemElementA = new Element('a', {href:'#remove-item-' + item, text:item});
        itemElementA.addEvent('click', (function(e) {
            e.stop();
            this.removeItem(item);
            e.target.dispose();
        }).bind(this));
        itemElement.adopt(itemElementA);
        this.parent.getElement('.list-editor-items').adopt(itemElement);
        this.parent.getElement('input[type=hidden]').set('value', this.delimiter + this.items.join(this.delimiter));
        this.element.set('value','');
    }
});

Element.implement({
    // Method: createCliprater
    //      apply the DR.Ung.Input.Cliprater() to element
    createCliprater: function () {
        return new DR.Ung.Input.Cliprater(this);
    }
    ,createDatePicker: function() {
		var showTime = this.hasClass('showTime');
		return new DR.Ung.Input.DatePicker(this, {show_time: showTime});
    }
    ,createResourceChecker: function() {
        return new DR.Ung.Input.Resource(this);
    }
    ,createListEditor: function() {
        return new DR.Ung.Input.Selector(this);
    }
});





