/**
 * create closure
 */
(function($) {
   //
   // plugin definition
   //
   $.fn.cityrpc = function(options) {
      // iterate and reformat each matched element
      return this.each(function() {
         $.fn.cityrpc.bindrpc(this, options)
      });
   }

   $.fn.cityrpc_ac = function(options) {
      // iterate and reformat each matched element
      return this.each(function() {
         var o = $.extend({}, $.fn.cityrpc.defaults, options);

         if ($.fn.metadata)
            $.extend(true, o, $(this).metadata());

         var p = { rpc_module : o.rpc_module,
                   rpc_class  : o.rpc_class,
                   call       : o.call
                 };
         if (o.rpc_params)
           $.extend(p, o.rpc_params);

         var ac_o = $.extend({}, $.fn.cityrpc.ac_defaults, o.ac_options);
         ac_o.cb_cityrpc = function (ax) {
            // Komplette Forms abschicken?
            if (o.rpc_sendform) {
               $(o.rpc_sendform).each(function() {
                  $.extend(p, $.fn.cityrpc.formToArray(this));
               })
            }

            // Mehrere Element-Werte mit übergeben
            if (o.rpc_attach)
            {
               jQuery.each(o.rpc_attach, function(i, val) {
                  p[i] = $(val).val();
               });
            }

            // Elementwert mit übergeben
            if (o.val_as)
               p[o.val_as] = ax.data.q;
            delete ax.data.q;

            $.extend(ax, {
               url : o.rpc_handler,
               data : $.extend(ax.data, p),
               dataType : o.rpc_datatype,
               type : p.rpc_type
            });
            return ax;
         };
         $(this).autocomplete('egal', ac_o)
      });
   }

   // $this ist das eingabefeld
   $.fn.cityrpc.bindrpc = function(el, options) {
      var $this = $(el);
      // build element specific options
      var o = $.extend({}, $.fn.cityrpc.defaults, options);

      if ($.fn.metadata)
         $.extend(true, o, $this.metadata());

      var p = { rpc_module : o.rpc_module,
                rpc_class  : o.rpc_class,
                call       : o.call
              };
      if (o.rpc_params)
         $.extend(p, o.rpc_params);
      
      if (o.rpc_sendform) {
         $(o.rpc_sendform + ' input[type="submit"]').unbind('click').bind('click', function(e) {
                     p[$(this).attr('name')] = $(this).val();
                     return true;
            }); 
      }

      $this.bind(o.event, function (e) {
         // Event-Callback aufrufen
         if (o.eventcallback && !o.eventcallback(e)) {
            e.stopPropagation();
            return false;
         }

         // Komplette Forms abschicken?
         if (o.rpc_sendform) {
            $(o.rpc_sendform).each(function() {               
               $.extend(p, $.fn.cityrpc.formToArray(this));
               a = {};
               a[el.name] = el.value;
               $.extend(p, a);
            })
         }

         // Mehrere Element-Werte mit Ã¼bergeben
         if (o.rpc_attach)
         {
            jQuery.each(o.rpc_attach, function(i, val) {
               p[i] = $(val).val();
               //window.console.log(val + ', ' + i + ": " + p[i]);
            });
         }

         // Elementwert mit übergeben
         if (o.val_as)
            p[o.val_as] = $this.val();

         $.fn.cityrpc.animate_out(o);

         // Das soll passieren
         var callback = function(data) {
            $(o.destination).html(data);
            $.fn.cityrpc.animate_in(o);
         };

         // Ajax-Request losschicken
         $.ajax({
            type: o.rpc_type,
            url: o.rpc_handler,
            data: p,
            dataType: o.rpc_datatype,
            success: callback
         });
         return true;
      });
      return $this;
   }

   // Diese FN soll ausgefÃ¼hrt wÃ¤hrend Event bearbeitet wird. true bedeutet: ok, ajax senden, sonst nicht
   $.fn.cityrpc.eventcallback = function(e) {
      if (e.type == 'keyup')
      {
         // nur bei modifikationen reagieren
         if (e.which < 46 && e.which != 8)
            return false;
      }
      return true;
   };


   $.fn.cityrpc.animate_in = function(options)
   {
      if (options.animate_in)
         jQuery(options.destination).animate(options.animate_in);
   }

   $.fn.cityrpc.animate_out = function(options)
   {
      if (options.animate_out)
         jQuery(options.destination).animate(options.animate_out);
   }

   function dbg(o, txt, pure)
   {
      if (window.console && window.console.log)
      {
         if (pure)
            window.console.log(txt + ": " + o);
         else
            window.console.log(txt + ": " + $.toJSON(o));
      }
   };

   $.fn.cityrpc.ac_defaults = { type : 'post' };
   //
   // plugin defaults
   //
   $.fn.cityrpc.defaults = {
      eventcallback : $.fn.cityrpc.eventcallback,
      event       : 'keyup', // mehrere Events mit space getrennt auflisten
      rpc_handler : '../rpc/default_ax_handler.php',
      rpc_class   : 'Test',
      rpc_module  : "",
      call        : 'get_user_list',
      rpc_type    : 'POST',
      rpc_params  : {},
      rpc_sendform: false,
      rpc_datatype: false,
      val_as      : false,
      destination : '#echobox',
      animate_out : false, //{ opacity: 'hide' },
      animate_in  : false,  //{ opacity: 'show' },
      ac_options  : $.fn.cityrpc.ac_defaults
   };


   /**
    * formToArray() gathers form element data into an array of objects that can
    * be passed to any of the following ajax functions: $.get, $.post, or load.
    * Each object in the array has both a 'name' and 'value' property.  An example of
    * an array for a simple login form might be:
    *
    * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
    *
    * It is this array that is passed to pre-submit callback functions provided to the
    * ajaxSubmit() and ajaxForm() methods.
    */
   $.fn.cityrpc.formToArray = function(form, semantic) {
       var a = {};
       if (this.length == 0) return a;

       var els = semantic ? form.getElementsByTagName('*') : form.elements;
       if (!els) return a;
       for(var i=0, max=els.length; i < max; i++) {
           var el = els[i];
           var n = el.name;
           if (!n) continue;

           var v = $.fn.cityrpc.fieldValue(el, true);
           /*
            * if (v && v.constructor == Array) {
               var va = {};
               for(var j=0, jmax=v.length; j < jmax; j++)
                   va[j] = v[j];
               a[n] = va;
           }
           else */
           if (v !== null && typeof v != 'undefined')
               a[n] = v;
       }
       return a;
   };

   /**
    * Returns the value of the field element.
    */
   $.fn.cityrpc.fieldValue = function(el, successful) {
       var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
       if (typeof successful == 'undefined') successful = true;

       if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
           (t == 'checkbox' || t == 'radio') && !el.checked ||
           (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
           tag == 'select' && el.selectedIndex == -1))
               return null;

       if (tag == 'select') {
           var index = el.selectedIndex;
           if (index < 0) return null;
           var a = [], ops = el.options;
           var one = (t == 'select-one');
           var max = (one ? index+1 : ops.length);
           for(var i=(one ? index : 0); i < max; i++) {
               var op = ops[i];
               if (op.selected) {
               var v = op.value;
               if (!v) // extra pain for IE...
                     v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                   if (one) return v;
                   a.push(v);
               }
           }
           return a;
       }
       return el.value;
   };

})(jQuery);
