(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() {
        var config = $(this).closest('form').find('#'+this.id+'_opts');        
        var opts = $.parseJSON(config.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 daterangepicker = new $.mw.form.control({
    bind: function(elem) {
      $('.mw_form_date_range', elem).mwbind('date_range',function() {
        var config = $(this).closest('form').find('#'+this.id+'_opts');        
        var opts = $.parseJSON(config.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]);
        }
        $.each('earliestDate latestDate maxDate minDate'.split(/\s/), function(i, key) {
          if (key in opts) opts[key] = parseMinMaxDate(opts[key]);
        });
        // console.debug([this,opts]);
        $(this).daterangepicker(opts);
        return true;
      });
    }
  });
  
  var binder = new $.mw.binder({
    bind: function(elem) {
      $.mw.form.bind(elem);
    }
  });
  
  $.widget('mw.formLink', {
    options: {
      dialogOpts: {modal: true, width: '80%'},
      ajaxParams: {}
    },
    _create: function() { 
      var self = this;
      // The element passed in will be an <a> hopefully
      if (!this.options.url && this.element.is('a')) {
        this.options.url = this.element.attr('href');
      }
      
      this.element.bind('click.formLink', function(e) {
          self.edit();
          e.preventDefault();
      });
    },
	destroy: function() {
		// this.element.unbind('click.formLink');
		$.Widget.prototype.destroy.call(this);
	},
    edit: function() {
      var self = this;
      
      var ajax = $.extend({}, this.options.ajaxParams, {url: this.options.url});
      $.ajax($.extend(ajax, {
        data: {format: 'json-form'},
        dataType: 'json',
        success: function(data, textStatus) {
          self.handle(data);
        },
        error: function(xhr, textStatus, thrown) {
          self.error(xhr, textStatus, thrown);
        }
      }));
    },
    error: function(xhr, textStatus, thrown) {
      var self = this;
      self._trigger('onError');
      var $dlg = $("<div>There was an error communicating with the server. <br/><strong>Status:</strong> "+textStatus+"<br/> <strong>Thrown:</strong>"+thrown+"<br/></div>");
      $dlg.append($("<a>Try Actual Form Page</a>").attr('href', self.options.url));
      if (xhr.responseText) {
        $dlg.append("<hr/><div style='max-height:20em;overflow:scroll'>"+xhr.responseText+"</div>");
      }
      var dlgOpts = $.extend({}, this.options.dialogOpts);
      dlgOpts.title = 'Communications Error';
      dlgOpts.buttons = {'Ok': function() {$(this).dialog('close');}};
      dlgOpts.close = function() { self._trigger('postEdit'); };
      $dlg.dialog(dlgOpts);
    },    
    submit: function($dlg, key, text) {
      var self = 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 = self.options.url, ajax = self.options.ajaxParams;
      self._trigger('preSave');
      ajax = $.extend({}, ajax, {
        url: url,
        dataType: 'json',
        success: function(data, textStatus) {
          $dlg.dialog('close');
          self.handle(data);
        },
        error: function(xhr, textStatus, thrown) {
          $dlg.dialog('close');
          self.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 self = this;
      self._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')
            {
              self.submit($dlg, data.buttons[text], text);              
            }
          }
          return false;
        }).append($('<input type="submit">').hide());
        var dlgOpts = $.extend({}, this.options.dialogOpts);
        dlgOpts.title = dlgOpts.title || self.element.text();
        if (!data.buttons) {
          data.buttons = {'Save':''};
        }
        dlgOpts.buttons = {};
        dlgOpts.close = function() { 
          self._trigger('postEdit'); 
          setTimeout(function(){ 
            $dlg.dialog('destroy'); 
          }, 1);
        };
        $.each(data.buttons, function(text, key){
          dlgOpts.buttons[text] = function() {
            if (key != 'delete' || confirm('Are you sure?'))
            self.submit($dlg, key, text);
          };
        });
        $dlg.dialog(dlgOpts);
        self._trigger('popped', false, $dlg);
      } else {
        // assume success!
        self._trigger('saved', false, data);
        self._trigger('postEdit');
      }
    }  
  });
  
  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);

