/*
---
description:     qkForm

authors:
  - Hamza Bahlaouane (http://quick2ouch.com)

license:
  - MIT-style license
  
Version: 
	1.0
	
requires:
  core/1.2.4:   '*'

provides:
  - qkForm
...
*/

	var QuickForm = new Class({
		Implements: Options,
		options: {
			speed:300,
			fx:Fx.Transitions.linear.easeOut
		},
		initialize: function(e,b){
			this.formContainerId = $(e);
			this.setOptions(b);
			
			// add qkFormdone class to the form
			if(this.formContainerId.hasClass('qkFormdone')) {return;}
			this.formContainerId.addClass('qkFormdone');

			
			// get all elements needed
			this.getSelects = this.formContainerId.getElements('select');
			this.getFields = this.formContainerId.getElements('input[type=text]');
			this.getPasswords = this.formContainerId.getElements('input[type=password]');
			this.getButtons = this.formContainerId.getElements('input[type=submit], input[type=reset],input[type=button]');
			this.getTextareas = this.formContainerId.getElements('textarea');
			this.getCheckboxs = this.formContainerId.getElements('input[type=checkbox]');
			this.getRadios = this.formContainerId.getElements('input[type=radio]');	
			
			// start parsing
			this.parseButtons();
			this.parseTextareas();
			this.parseFields();
			this.parseCheckboxs();
			this.parseRadios();
			this.parseSelects();
		},
		parseButtons:function(){
			this.getButtons.each(function(item){
			
				// create new button element
				var newBtn = new Element('button', {
					'id': item.id,
					'name': item.name,
					'type': item.type,
					'class': 'qkFormButton',
					// add click event and hover
					'events': {
					/*
						'click': function(){
							newBtn.addClass('qkFormButton_click');
						},
						'blur': function(){
							newBtn.removeClass('qkFormButton_click');
						},
					*/
						'mouseover': function(){
            				newBtn.addClass('qkFormButton_hover');
						},
						'mouseleave': function(){
            				newBtn.removeClass('qkFormButton_hover');
						}
					}
				});
				
					// element & inserations
					var myFirstSpan  = new Element('span');
					var mySecondSpan  = new Element('span');
					mySecondSpan.appendText(item.value); 
					mySecondSpan.inject(myFirstSpan); 
					myFirstSpan.inject(newBtn); 
				
					newBtn.inject(item,'before');
					item.destroy();
					// i used inject then destroy because replaces won't work :(
				}); // for end's here 
		},
		
		parseTextareas:function(){
			this.getTextareas.each(function(textarea){
				if(textarea.hasClass('qkFormdone')) {return;}
				textarea.addClass('qkFormdone');

				var myDiv  = new Element('div');
				// prepare the html code and put it inside myDiv elemet , without using createElement a lot of time to create the table html code
				myDiv.set('html','<table cellspacing="0" cellpadding="0" border="0" class="qkFormTextarea" ><tr><td id="qkFormTextarea-tl"></td><td id="qkFormTextarea-tm"></td><td id="qkFormTextarea-tr"></td></tr><tr><td id="qkFormTextarea-ml">&nbsp;</td><td id="qkFormTextarea-mm"><div class="qkFormTextarea-placeholder"></div></td><td id="qkFormTextarea-mr">&nbsp;</td></tr><tr><td id="qkFormTextarea-bl"></td><td id="qkFormTextarea-bm"></td><td id="qkFormTextarea-br"></td></tr></table>');
		
				myDiv.inject(textarea,'before');
				textarea.inject(myDiv.getElement('.qkFormTextarea-placeholder'));
				//if(textarea.get('html') == "") textarea.set('text',' '); // fix bug on ie7 , textarea is too small when it is empty
				
				//tx_placeholder.set('html',tx_placeholder.get('html')+'</textrea>');
				
				
				// hover events
				
				myDiv.addEvents({
					'mouseover': function(){
						myDiv.getElement('table').addClass('qkFormTextarea-hover');
					},
					'mouseleave': function(){
            			myDiv.getElement('table').removeClass('qkFormTextarea-hover');
					}
				});
				
				
			});// for end's here 
		},
		
		parseFields:function(){
			this.getFields.each(function($input){
			
				if($input.hasClass('jqtranformdone')) {return;}
				$input.addClass('jqtranformdone');
		
		
				// setup deaut width
				var inputSize=$input.getSize().x;
				
					if($input.size){
						inputSize = $input.size*10;
						$input.setStyle('width',inputSize);
					}

				// add qkFormInput class
				$input.addClass("qkFormInput");

				// setup environment
				var myFirstDiv  = new Element('div',{'class':'qkFormInputWrapper'});
				var mySecondDiv  = new Element('div',{'class':'qkFormInputInner'});
				var myThirdDiv  = new Element('div');
				mySecondDiv.inject(myFirstDiv);
				myThirdDiv.inject(mySecondDiv);
				myFirstDiv.inject($input,'before');
				$input.inject(myThirdDiv);
			

				
				// var $wrapper = $input.getParent().getParent().getParent();
				var $wrapper = myFirstDiv;
				$wrapper.setStyle("width", inputSize+10);

				
				// focus & blur & hover events
				$input.addEvents({
					'focus': function(){
						$wrapper.addClass("qkFormInputWrapper_focus");
					},
					'blur': function(){
						$wrapper.removeClass("qkFormInputWrapper_focus");
					},
					'mouseover': function(){
						$wrapper.addClass("qkFormInputWrapper_hover");
					},
					'mouseleave': function(){
            				$wrapper.removeClass("qkFormInputWrapper_hover");
					}
				});

				/* If this is safari we need to add an extra class */
				if(Browser.Engine.webkit){
					$wrapper.addClass('qkFormSafari');
					$input.setStyle('width',getSize().x+16);
				}

			});// for end's here 

			this.getPasswords.each(function($input){
			
				if($input.hasClass('jqtranformdone')) {return;}
				$input.addClass('jqtranformdone');
		
		
				// setup deaut width
				var inputSize=$input.getSize().x;
				
					if($input.size){
						inputSize = $input.size*10;
						$input.setStyle('width',inputSize);
					}

				// add qkFormInput class
				$input.addClass("qkFormInput");

				// setup environment
				var myFirstDiv  = new Element('div',{'class':'qkFormInputWrapper'});
				var mySecondDiv  = new Element('div',{'class':'qkFormInputInner'});
				var myThirdDiv  = new Element('div');
				mySecondDiv.inject(myFirstDiv);
				myThirdDiv.inject(mySecondDiv);
				myFirstDiv.inject($input,'before');
				$input.inject(myThirdDiv);
			

				
				// var $wrapper = $input.getParent().getParent().getParent();
				var $wrapper = myFirstDiv;
				$wrapper.setStyle("width", inputSize+10);

				
				// focus & blur & hover events
				$input.addEvents({
					'focus': function(){
						$wrapper.addClass("qkFormInputWrapper_focus");
					},
					'blur': function(){
						$wrapper.removeClass("qkFormInputWrapper_focus");
					},
					'mouseover': function(){
						$wrapper.addClass("qkFormInputWrapper_hover");
					},
					'mouseleave': function(){
            				$wrapper.removeClass("qkFormInputWrapper_hover");
					}
				});

				/* If this is safari we need to add an extra class */
				if(Browser.Engine.webkit){
					$wrapper.addClass('qkFormSafari');
					$input.setStyle('width',getSize().x+16);
				}

			});// for end's here 
		},
		
		parseCheckboxs:function(){
			this.getCheckboxs.each(function($input){
				
				if($input.hasClass('qkFormHidden')) {return;}
				else{$input.addClass('qkFormHidden');}
				$input.setStyle('display','none'); // qkFormHidden won't work in some case , pfff !!
		
		
				// get the next label element , we need to position & add a click event to it
				var nextLabel = $input.getPrevious('label');
				if(nextLabel != null) nextLabel.setStyles({'cursor':'pointer','padding':'3px 0 0 2px'});
		
				// setup environment
				var mySpan = new Element('span',{'class':'qkFormCheckboxWrapper'});
				var myAnchor = new Element('a',{'class':'qkFormCheckbox'});
				myAnchor.inject(mySpan);

				
				// add qkFormChecked class when input is already checked , for loading stuff ... 
				if($input.getProperty('checked')){
					myAnchor.addClass('qkFormChecked');
				}
		
				// click event : add checked class & remove it
				myAnchor.addEvent('click',function(){
					if($input.getProperty('disabled')){return false;}
					myAnchor.addClass('qkFormChecked');
					
					if($input.getProperty('checked') && myAnchor.hasClass('qkFormChecked')){
						myAnchor.removeClass('qkFormChecked');
						$input.setProperty('checked',false);
					}
					else{
						$input.setProperty('checked','checked');
						myAnchor.addClass('qkFormChecked');
					}

					return false;
				});

				// next label element do the same thing as anchor, so no need the repeat the same event , just clone it
                if(nextLabel)
                    nextLabel.cloneEvents(myAnchor,'click');
				
				// insert the element now
				mySpan.inject($input,'before');
				$input.inject(mySpan);
				
			});// for end's here 
		},
		
		parseRadios:function(){
			this.getRadios.each(function($input){
				
				if($input.hasClass('qkFormHidden')) {return;}
				else{$input.addClass('qkFormHidden');}
				$input.setStyle('display','none');
		
				var nextLabel = $input.getParent('label');
				if(nextLabel != null) nextLabel.setStyles({'cursor':'pointer','padding':'5px 0 0 2px'});
		
				var mySpan = new Element('span',{'class':'qkFormRadioWrapper'});
				var myAnchor = new Element('a',{'class':'qkFormRadio','rel':$input.name});
				myAnchor.inject(mySpan);

				if($input.getProperty('checked')){
					myAnchor.addClass('qkFormChecked');
				}
		

				myAnchor.addEvent('click',function(){
					if($input.getProperty('disabled')){return false;}
			
					// uncheck all others of same name input radio elements
					this.formContainerId.getElements('input[name="'+$input.getProperty('name')+'"]').each(function(rd){
						rd.setProperty('checked',false);
					});
					this.formContainerId.getElements('a[rel="'+$input.getProperty('name')+'"]').each(function(rd){
						rd.removeClass('qkFormChecked');
					});
											
					if($input.getProperty('checked') && myAnchor.hasClass('qkFormChecked')){
						myAnchor.removeClass('qkFormChecked');
						$input.setProperty('checked',false);
					}
					else{
						$input.setProperty('checked','checked');
						myAnchor.addClass('qkFormChecked');
					}

					

					return false;
				}.bind(this));
				
				nextLabel.cloneEvents(myAnchor,'click');
				
				mySpan.inject($input,'before');
				$input.inject(mySpan);
				
			}.bind(this)); // for end's here 
		},
		
        updateSelect: function($select){
            
        },
        
		parseSelects:function(){
			this.getSelects.each(function($select,index){
				
				var $getSize = $select.getSize();
				var anchorMax = 1;
				var $hideAllMenusTimeout = null;
				
				if($select.hasClass('qkFormHidden')) {return;}
				if($select.multiple) {return;}
				$select.addClass('qkFormHidden');

				/* First thing we do is Wrap it */
				var myDiv  = new Element('div',{'class':'qkFormSelectWrapper'});

				var mySecDiv = new Element('div');
				mySecDiv.inject(myDiv);
				var mySpan = new Element('span');
				mySpan.inject(mySecDiv);

				var myAnchor  = new Element('a',{'href':'#','class':'qkFormSelectOpen'});
				myAnchor.inject(mySecDiv);

				var myUl = new Element('ul',{'width':$getSize.x,'overflow':'none'});
				
				myUl.inject(myDiv);

				var $firstSpan = mySpan;
				var $ul = myUl;
		

		

				var currentY = 0;
				$select.getElements('option').each(function(op,i){
					var oli = new Element('li');
					oli.setStyle('margin',0);
					var oa = new Element('a',{'index':i});
					if(op.get('selected')) oa.addClass('selected');
					currentY+= $getSize.y;
					oa.set('rel',currentY);
					
					oa.appendText(op.get('html'));
					oa.inject(oli);
					oli.inject(myUl);
					anchorMax++;
				});

				
				
				$anchors = myUl.getElements('a');
				$open = myDiv.getElement('a.qkFormSelectOpen');

				// tween effect ( control ul height )
				var $myFx = new Fx.Tween($ul,{duration:this.options.speed,transition:this.options.fx});

				$anchors.each(function(iti){
					iti.addEvents({
						'click': function(){
							if(myDiv.getElement('a.selected')) myDiv.getElement('a.selected').removeClass('selected');
							iti.addClass('selected');
                            
                            var els = $select.retrieve('elements') || $select.getElements('option');
                            
							if ($select[0].selectedIndex != iti.get('index') && $select[0].onchange) { $select[0].selectedIndex = iti.get('index'); $select[0].onchange(); }
							$select[0].selectedIndex = iti.get('index');
                            
                            var el = els[iti.get('index')].get('value');
                            $select.set('value', el).fireEvent('change');
                            
							// $firstSpan.set('text',iti.get('html')); // error on ie7 when using html method
							mySpan.set('text', iti.get('text'));
							$myFx.start('height', 0).chain(function(){ $ul.setStyle('display','none'); });
							$anchors.each(function(w){w.removeClass('hover');});
							return false;
						},				
						'mouseover': function(){
            					if($hideAllMenusTimeout) $clear($hideAllMenusTimeout);
								if(iti.hasClass('selected')){
									iti.removeClass('selected');
									iti.addClass('_selected');
								}
								iti.addClass('hover');

						},
						'mouseleave': function(){
								iti.removeClass('hover');
								if(iti.hasClass('_selected')){
									iti.removeClass('_selected');
									iti.addClass('selected');
								}
						}
					});

				});

				
				
				$anchors[$select.selectedIndex].fireEvent('click');
				mySpan.setStyle('width',$getSize.x);
		
				$open.addEvent('click',function(e){
                    
					e.stop(); 
					if($hideAllMenusTimeout) $clear($hideAllMenusTimeout);
					$$(this.getSelects).fireEvent('hide');
					
					$anchors.each(function(w){w.removeClass('hover');});
					
					if($ul.getStyle('display') == 'none'){
						$ul.setStyles({'display': 'block', 'overflow-x': 'hidden', 'z-index': 100});
                        anchorMax = anchorMax > 8? 8: anchorMax;
                        
						// start tween effect
						$myFx.start('height', $getSize.y*anchorMax);
                        
						// set timeout : if the menu is opened and nothing happen in the next 2 sec , hide the menu
						$hideAllMenusTimeout = (function(){
							$clear($hideAllMenusTimeout);
							$ul.fireEvent('hide');	
						}).delay(2000);
					}
					else{
						$myFx.start('height', 1).chain(function(){ $ul.setStyle('display','none');  });
					}
					// scroll to y cordinate when the menu is open
					myUl.scrollTo(0, myUl.getElement('a.selected').get('rel'));
					return false;

				}.bind(this));
				
				
				//  mouseleave , when leaving the contener div , hide the mneu
				/*
				myDiv.addEvent('mouseleave',function(){
						if($ul.getStyle('display') == 'block'){
							$hideAllMenusTimeout = (function(){
								$clear($hideAllMenusTimeout);
								$ul.fireEvent('hide');		
							}).delay(50);
						}
				});
				*/
				
				// first span & drop button are the same
				mySpan.cloneEvents($open, 'click');


				// hide event , no need to write this code everytime we want to hide menus , just firEvent the ul element
				$ul.addEvent('hide',function(){
					if($ul.getStyle('display') == 'block' && $hideAllMenusTimeout){
						$clear($hideAllMenusTimeout);
						$myFx.start('height', 0).chain(function(){ $ul.setStyle('display','none'); });
						$anchors.each(function(w){w.removeClass('hover');});
					}
				});


				// Set the new width
				var iSelectWidth = $getSize.x;
				var oSpan = mySpan;
				var newWidth = (iSelectWidth > oSpan.getSize().x)?iSelectWidth+$open.getSize().x:myDiv.getSize().x;
				myDiv.setStyle('width',newWidth+20);
				$ul.setStyle('width',(newWidth-2)+20);
				oSpan.setStyle('width',iSelectWidth+20);

				
				// insert the new select
				myDiv.inject($select,'before');
				$select.inject(myDiv);

			
			}.bind(this));// for end's here 
		}
	
	});
    
    
var GeoWidget = new Class({
   'Implements': Options,
   'options':{
        'url': '',
        'initial': null
   },
   'initialize': function(id, options){
        this.setOptions(options);
        
        this.parent = $(id);
        this.selects = this.parent.getElements('select');
        this.initial = this.selects[1].get('value');
        
        this.opts = this.selects[1].getElements('option[value]');
        
        if(this.another_parent = this.selects[1].getParent('.qkFormSelectWrapper')){
            this.another_select = this.another_parent.getElements('ul')[0];
            this.another_opts = this.another_select.getElements('li:not(:first-child)');
        }
        
        this.selects[0].store('elements', this.selects[0].getElements('option'));
        this.selects[1].store('elements', this.selects[1].getElements('option'));
        
        this.disposeAll();
        
        this.selects[0].addEvent('change', this.changed.bind(this)).fireEvent('change');
    },
    
    'disposeAll': function(){
        this.opts.dispose();
        if(this.another_opts)
            this.another_opts.dispose();
    },
   
   'changed': function(){
        if(!this.selects[0].get('value')) return this.disposeAll();
        
        var that = this;
        new Request.JSON({'url': this.options.url.substitute({'id': this.selects[0].get('value')}),
            'onSuccess': function(data){
                
                var current = parseInt(that.selects[1].get('value')), setcurrent;
                
                var enabled = data.map(function(item){
                    return item[0];
                });
                
                that.disposeAll();
                that.opts.each(function(option, index){
                    var value = parseInt(option.get('value')) || null;
                    if(!value || enabled.indexOf(value) != -1){
                        enabled.erase(value);
                        option.inject(that.selects[1]);
                        
                        if(that.another_opts)
                            that.another_opts[index].inject(that.another_select);
                        
                        if(current == value) setcurrent = value;
                    }
                });
                
                if(that.initial) setcurrent = that.initial;
                if(setcurrent) that.selects[1].set('value', setcurrent);
                else that.selects[1].set('value', '');
                
                that.selects[1].getParent('.qkFormSelectWrapper').getElements('.qkFormSelectOpen').getPrevious('span').set('text', that.selects[1].getElements('option[selected]')[0].get('text'));
            }
        }).get();
        
        ///this.initial = null;
    }
});


var MultilineForm = new Class({
    Implements: [Options],
    
    options: {
        button_title: 'Добавить строку',
        can_delete_base: true
    },
    
    initialize: function(form_name, form_count, options){
        
        this.setOptions(options);
        
        this.form_name = form_name;
        this.form_count = form_count;
        this.form = $$('#empty_form_'+form_name+' tr')[0];
        this.base_from = $('full_'+form_name+'_form');
        this.top_form = $('set_'+form_name).getParent('form');
        
        this.setup();
        
        this.count = parseInt($$('#set_'+form_name+' [name$="TOTAL_FORMS"]')[0].get('value')),
        this.have = $$('#set_'+form_name+' table.form tr').length,
        this.add_button = $$('#add_form_'+form_name+' a');
        
        this.add_button.addEvent('click', this.addRow.bind(this));
        
        for(var i = this.have; i < this.count-1; i++)
            this.addRow.apply(this);
    },
    
    setup: function(){
        new Element('p', {
                'class': 'mt10 formset_adder',
                'id': 'add_form_'+this.form_name
            }).adopt([
                new Element('a', {
                    'href': '#',
                    'class': 'button b-tiny',
                    'text': '+'
                }),
                new Element('a', {
                    'href': '#',
                    'class': 'blue smallbuttonright',
                    'text': this.options.button_title
                })
            ]).inject(this.base_from.getParent('table.form'), 'after');
    
        $('empty_form_'+this.form_name).dispose();
        new QuickForm(this.top_form);
        
        this.base_from.getElements('tr.set-form').filter(function(tr){ return tr.getElements('input[name$=DELETE]').length == 0; }).each((function(el){
            var td = new Element('td');
            td.set('html', '<span class="qkFormCheckboxWrapper"><del></del></span>');
            del = td.getElements('del')[0];
            td.inject(el, 'bottom');

            new Element('a', {
                'href': '#',
                'rel': this.form_count,
                'class': 'button b-tiny delete-button',
                'html': '&minus;',
                'style': 'font-size: 210% !important'
            }).addEvent('click', this.removeRow.bind(this, del)).inject(
                del.getParent('.qkFormCheckboxWrapper'),
                'before'
            );
        
        }).bind(this));
        
        if(this.options.can_delete_base)
        this.base_from.getElements('input[name$=DELETE]').each((function(del){
            del.getParent('.qkFormCheckboxWrapper').setStyle('display', 'none');
            
            new Element('a', {
                'href': '#',
                'rel': this.form_count,
                'class': 'button b-tiny delete-button',
                'html': '&minus;',
                'style': 'font-size: 210% !important'
            }).addEvent('click', this.removeRow.bind(this, del)).inject(
                del.getParent('.qkFormCheckboxWrapper'),
                'before'
            );        
        }).bind(this));
        
        this.top_form.getElements('[name$="series_number"]').meiomask('fixed.money');
        
        if(this.top_form.getElements('.delete-button').length)
            this.top_form.getElements('.delete-button')[0].destroy();
    },
    
    addRow: function(){
        
        var el = this.form.clone(true, true);
        el.getElements('[name]').each((function(item){
            item.set('name', item.get('name').replace(/__prefix__/g, this.form_count)).set('id', item.get('id').replace(/__prefix__/g, this.form_count));
        }).bind(this));
        el.getElements('[name$="series_number"]').meiomask('fixed.money');
        el.inject(this.base_from, 'bottom');
        
        new QuickForm(el);
        
        var del = el.getElements('input[name$=DELETE]');
        
        if(del.length){
            del = del[0];
            del.getParent('.qkFormCheckboxWrapper').setStyle('display', 'none');
        }  else {
            var td = new Element('td');
            td.set('html', '<span class="qkFormCheckboxWrapper"><del></del></span>');
            del = td.getElements('del')[0];
            td.inject(el, 'bottom');
        }

        new Element('a', {
            'href': '#',
            'rel': this.form_count,
            'class': 'button b-tiny delete-button',
            'html': '&minus;',
            'style': 'font-size: 210% !important'
        }).addEvent('click', this.removeRow.bind(this, del)).inject(
            del.getParent('.qkFormCheckboxWrapper'),
            'before'
        );

        this.form_count++;
        $$('#set_'+this.form_name+' [name$="TOTAL_FORMS"]')[0].set('value', this.form_count);

        return false;
    },
    
    removeRow: function(del){
        var deleted_id = del.get('rel'),
            deleted_row = del.getParent('tr');
        this.form_count--;
        $$('#set_'+this.form_name+' [name$="TOTAL_FORMS"]')[0].set('value', this.form_count);
        
        deleted_row.getAllNext('tr').each(function(row, i){
            var rel = row.getElements('.delete-button')[0].get('rel');
            row.getElements('[name]').each(function(item){
                item.set('name', item.get('name').replace(new RegExp('-'+rel+'-', 'g'), '-'+(rel-1)+'-'))
                    .set('id', item.get('id').replace(new RegExp('-'+rel+'-', 'g'), '-'+(rel-1)+'-'));
            });
        });
        
        deleted_row.destroy();
        
        return false;
    }
    
    
});


function makeSelector(id, func){
    $$('#'+id+' [rel]').addEvent('click', function(){
        if(this.getParent('li').hasClass('current')) return false;
        
        $$('#'+id+' .current').removeClass('current');
        this.getParent('li').addClass('current');
        
        $$('#'+id+' ~ .stat').setStyles({'height': 0, 'overflow': 'hidden'}).each(function(item){
            item.getChildren('div[id]').setStyle('display', 'none');
        });
        
        if($(this.get('rel').split('|')[0])){
            $(this.get('rel').split('|')[0]).getChildren('div[id]').setStyle('display', '');
            $(this.get('rel').split('|')[0]).setStyle('height', '');
        }
        
        if(func) func(this.get('rel'));
        
        return false;
    })[0].fireEvent('click');
}

function overItem(item){ $$('a[rel]').setStyle('text-decoration', 'none'); $$('a[rel="'+item+'"]').setStyle('text-decoration', 'underline') }
function outItem(item){  }

