(function($){
  $.mw = $.extend($.mw?$.mw:{}, {
    form: {
      controls: [],
      registerControl: function(control) {
        this.controls.push(control);
      },
      // bind(element) - binds editors to element.
      bind: function(elem) {  
        if (elem == undefined) elem = document;
        var $elem = $(elem); 
        $.each(this.controls, function(k, v) {
          v.bind($elem);
        });
      }            
    }
  });
  // MW_Form_Control class:
  $.mw.form.control = function(opts) {
    $.extend(this, opts);
    $.mw.form.registerControl(this);
  };
  
  $.mw.form.control.prototype.bind = function($elem) {
    alert('Unbound editor!');
  };
  
  var datepicker = new $.mw.form.control({
    bind: function(elem) {
      $('.mw_form_date', elem).each(function() {
        opts = eval("(" + $('#'+this.id+'_opts').text() + ")");
        function parseMinMaxDate(value) {
          if (!value) return undefined;
          var parts = /(\d+)-(\d+)-(\d+)/.exec(value);
          // console.debug(parts);
          return new Date(parts[1], parts[2]-1, parts[3]);
        }
        if (opts.maxDate) { opts.maxDate = parseMinMaxDate(opts.maxDate); }
        if (opts.minDate) { opts.minDate = parseMinMaxDate(opts.minDate); }
        // console.debug([this,opts]);
        $(this).datepicker(opts);
      });      
    }
  });
  
  var binder = new $.mw.binder({
    bind: function(elem) {
      $.mw.form.bind(elem);
    }
  });
  
  var formLink = $.extend({
    _init: function() {
      var widget = this, element = this.element;
      // The element passed in will be an <a> hopefully
      if (!this._getData('url') && element.is('a')) this._setData('url',element.attr('href'));
      element.bind('click', function() {
          widget.edit();
          return false;
      });
    },
    edit: function() {
      var widget = this, element = this.element;
      var url = this._getData('url'), ajax = this._getData('ajaxParams');
      $.ajax($.extend({}, ajax, {
        url: url,
        data: {format: 'json-form'},
        dataType: 'json',
        success: function(data, textStatus) {
          widget.handle(data);
        },
        error: function(xhr, textStatus, thrown) {
          widget.error(xhr, textStatus, thrown);
        }
      }));
    },
    error: function(xhr, textStatus, thrown) {
      var widget = this;
      widget._trigger('onError');
      var $dlg = $("<div>There was an error communicating with the server.</div>");
      if (xhr.responseText) {
        $dlg.append("<hr/>"+xhr.responseText);
      }
      var dlgOpts = $.extend({}, this._getData('dialogOpts'));
      dlgOpts.title = 'Communications Error';
      dlgOpts.buttons = {'Ok': function() {$(this).dialog('close');}};
      dlgOpts.close = function() { widget._trigger('postEdit'); };
      $dlg.dialog(dlgOpts);
    },    
    submit: function($dlg, key, text) {
      var widget = this;
      var $form = $dlg.find('form');
      $form.prepend($('<input name="format" value="json-form" type="hidden">'),$('<input type="hidden" name="'+key+'">').val(text));
      var url = widget._getData('url'), ajax = widget._getData('ajaxParams');
      widget._trigger('preSave');
      ajax = $.extend({}, ajax, {
        url: url,
        dataType: 'json',
        success: function(data, textStatus) {
          $dlg.dialog('close');
          widget.handle(data);
        },
        error: function(xhr, textStatus, thrown) {
          $dlg.dialog('close');
          widget.error(xhr, textStatus, thrown);
        }
      });
      if(window.CKEDITOR) $form.find('[name]').each(function() {
        var cke = CKEDITOR.instances[$(this).attr('name')];
        if (cke) $(this).val(cke.getData());
      });
      $form.ajaxSubmit(ajax);
    },
    handle: function(data) {
      var widget = this;
      widget._trigger('preEdit');
      if (data.form) {
        var $dlg = $('<div />').each(function() { this.innerHTML = data.form });
        $.mw.bind($dlg);
        $dlg.find('form').submit(function() {
          var buttons = $dlg.dialog('option', 'buttons');
          for (text in buttons) {
            var key = data.buttons[text]
            if (key == 'save' || key == 'submit')
            {
              widget.submit($dlg, data.buttons[text], text);              
            }
          }
          return false;
        }).append($('<input type="submit">').hide());
        var dlgOpts = $.extend({}, this._getData('dialogOpts'));
        dlgOpts.title = dlgOpts.title || widget.element.text();
        if (!data.buttons) {
          data.buttons = {'Save':''};
        }
        dlgOpts.buttons = {};
        dlgOpts.close = function() { widget._trigger('postEdit'); $dlg.remove().dialog('destroy'); };
        $.each(data.buttons, function(text, key){
          dlgOpts.buttons[text] = function() {
            widget.submit($dlg, key, text);
          };
        });
        $dlg.dialog(dlgOpts);
        widget._trigger('popped', false, $dlg);
      } else {
        // assume success!
        widget._trigger('saved', false, data);
        widget._trigger('postEdit');
      }
    }  
  });
  $.widget('mw.formLink', formLink);
  $.mw.formLink.defaults = {
    dialogOpts: {modal: true, width: '80%'},
    ajaxParams: {}
  };
  
  if ($.ui && $.ui.dialog) {
    /***
     * Pacth for dialog-fix ckeditor problem [ by ticket #4727 ]
     * 	http://dev.jqueryui.com/ticket/4727
     */

    $.extend($.ui.dialog.overlay, { create: function(dialog){
    	if (this.instances.length === 0) {
    		// prevent use of anchors and inputs
    		// we use a setTimeout in case the overlay is created from an
    		// event that we're going to be cancelling (see #2804)
    		setTimeout(function() {
    			// handle $(el).dialog().dialog('close') (see #4065)
    			if ($.ui.dialog.overlay.instances.length) {
    				$(document).bind($.ui.dialog.overlay.events, function(event) {
    					var parentDialog = $(event.target).parents('.ui-dialog');
    					if (parentDialog.length > 0) {
    						var parentDialogZIndex = parentDialog.css('zIndex') || 0;
    						return parentDialogZIndex > $.ui.dialog.overlay.maxZ;
    					}

    					var aboveOverlay = false;
    					$(event.target).parents().each(function() {
    						var currentZ = $(this).css('zIndex') || 0;
    						if (currentZ > $.ui.dialog.overlay.maxZ) {
    							aboveOverlay = true;
    							return;
    						}
    					});

    					return aboveOverlay;
    				});
    			}
    		}, 1);

    		// allow closing by pressing the escape key
    		$(document).bind('keydown.dialog-overlay', function(event) {
    			(dialog.options.closeOnEscape && event.keyCode
    					&& event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
    		});

    		// handle window resize
    		$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
    	}

    	var $el = $('<div></div>').appendTo(document.body)
    		.addClass('ui-widget-overlay').css({
    		width: this.width(),
    		height: this.height()
    	});

    	(dialog.options.stackfix && $.fn.stackfix && $el.stackfix());

    	this.instances.push($el);
    	return $el;
    }});
  }
  
})(jQuery);
