/**
 * jquery.gadget.js
 * http://www.redredred.com.au/
 *
 * Requires:
 * - jquery 1.3.x 
 * - jcache plugin (http://www.skidvn.com/jcache) if you want caching
 *
 * Copyright (c) 2009 Rob Monie
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *   
 * @author Rob Monie
 * @version 1.0
 */
(function($) {
    
    
    /**
     * setup static gadget registry
     */
    $.gadget = function() {
        
        $.debug = $.debug || function(){};
        
        return {
            register : function(type, options) {
                var gadget = $.extend({
                    events : {},
                    initialize : function() {}
                }, options);
              
                gadget.type = type;
                $.gadget[type] = gadget;
                $.debug("Registered Gadget: " + type);
                return gadget;
            }
        };
    }();
    

    $.fn.gadget = function(type, options) {
        
        var gadgetPrototype = $.gadget[type];
        
        if (!gadgetPrototype) {
            $.debug("Error: No gadget has been registered with the type: '" + type + "'");
            return;
        }
      
        var gadget = $.extend({
            cache : false,
            method : "html",
            baseUrl : "",
            urlParams : {},
            settings : {},
            data : {},
            cssClass: "",
            graphs : {},
            postInitialize: function() {}
            }, gadgetPrototype, options);

        return this.each(function() {
            $.debug("load gadget " + type);
            
            gadget.boundEvents = [];
            gadget.targetElement = $(this);
            
            gadget.getData = function(key) {
                return gadget.data[key];
            }

            gadget.setData = function(key, value) {
                if(value !== undefined) {
                    gadget.data[key] = value;
                }
                return gadget;
            }
            
            gadget.removeData = function(key) {
                if(value !== undefined) {
                    delete gadget.data[key];
                }
                return gadget;
            }
            
            gadget.destroy = function(callback) {
                destroyGadget(this, callback);
            };
    
            gadget.bind = function(eventName, callback) {
                bindEvent(gadget, eventName, callback);
                return gadget;
            }
                
            gadget.trigger = function(type, data) {
                $(document).trigger(type, data);
                return gadget;
            }
            
            gadget.find = function(selector) {
                return gadget.element.find(selector);
            }
           
            gadget.reload = function(callback, urlParams, baseUrl) {
                if(urlParams) {
                  gadget.urlParams = urlParams;
                }
                if(baseUrl) {
                  gadget.baseUrl = baseUrl;
                }
                
                gadget.method = "replaceWith";
                gadget.targetElement = gadget.element;
                loadHtml(gadget);
                return gadget.element;
            }
            
            gadget.setLanguage = function() {
              if(gadget.urlParams.lang) {
                gadget.lang = gadget.urlParams.lang;
              } else {
                gadget.lang = 'de';
              }
            }
            
            gadget.loadConfig = function(callback) {
              var configFile = gadget.baseUrl.split('/');
              configFile.pop();
              configFile = configFile.join('/') + '/config.json';
              
              $.get(configFile, function(result) {
                gadget.settings = eval(result);
                callback();
              });
            }
            
            // Reload gadget with original config
            loadHtml(gadget);
            
            // getLabels(gadget);
            return $(gadget.element);
        });

    };


    /*-------PRIVATE METHODS ------ */

    function destroyGadget(gadget, callback) {
        unbindEventsIncludingChildren(gadget);
        if (callback) {
            callback();
        }
        gadget.element.remove();
    }

    /*Unbind all events bound to this gadget*/
    function unbindEvents(gadget) {
        $.debug("unbinding events for gadget: " + gadget.type);
        for (var i = 0; i < gadget.boundEvents.length; i++) {
            var e = gadget.boundEvents[i];
            $(document).unbind(e.type, e.fn);
        }
        gadget.element.removeData("gadget");
    }
   
    /*Unbind all events bound to this gadget*/
    function unbindEventsIncludingChildren(gadget) {
        
        var $childGadgetElements = $(gadget.element).find(":gadget");
          $childGadgetElements.each(function() {
             var childGadget = $(this).data("gadget");
             if(childGadget) {
                unbindEvents(childGadget);
             }
          });

      unbindEvents(gadget);
    }
   
    /*bind an event to this gadget */
    function bindEvent(gadget, type, callback) {
        $(document).bind(type, callback);
        gadget.boundEvents.push({
            type : type,
            fn : callback
        });
    }

    /*load the html for this gadget */
    function loadHtml(gadget) {
        getTemplate(gadget, function(htmlContent) {
            
            if(gadget.method === "replaceWith") {
               unbindEventsIncludingChildren(gadget);
            } else if (gadget.method === "html") {
                gadget.targetElement.find(":gadget").each(function() {
                    unbindEvents($(this).data("gadget"));
                });
            }

            var newElement = insertIntoDom(htmlContent, gadget);
            gadget.element = $(newElement);
            gadget.element.data("gadget", gadget);
            
            if($.isFunction(gadget.dialog)) {
                gadget.element.dialog(gadget.dialog());
            } else if(gadget.dialog) {
                gadget.element.dialog(gadget.dialog);
            }
            
            gadget.initialize();
            gadget.postInitialize(gadget);
        });
    }

    function getTemplate(gadget, callback) {
        
        if(gadget.cache && $.jCache.getItem(gadget.baseUrl)) {
           $.debug("Using cached resource for '" + gadget.baseUrl + "'");
           callback($.jCache.getItem(gadget.baseUrl));
           return;
        } 
        
        $(document).trigger("gadget_pre_load", gadget);
        $.get(gadget.baseUrl, gadget.urlParams, function(result) {
            $(document).trigger("gadget_post_load", gadget);
            if(gadget.cache) {
               $.jCache.setItem(gadget.baseUrl, result);
            }
            callback(result);
         });
    }

    function insertIntoDom(htmlContent, gadget) {
        var domElement = $("<div class=\"gadget " + gadget.type + "_gadget "  + gadget.cssClass + "\">" + htmlContent + "</div>");
        gadget.targetElement[gadget.method](domElement);
        return domElement;
    }
    
    // function loadSettings(gadget) {
    //   var configFile = gadget.baseUrl.split('/');
    //   configFile.pop();
    //   configFile = configFile.join('/') + '/config.js';
    //   $.get(configFile, function(result) {
    //     gadget.settings = eval(result);
    //   });
    // }
    
    // function gadgetDir(gadget) {
    //   var dir = gadget.baseUrl.split('/');
    //   dir.pop();
    //   return dir.join('/');
    // }



}(jQuery));

/* add a gadget selector */
jQuery.extend($.expr[':'],{
    gadget: function(element) {
        return jQuery(element).data('gadget') !== undefined;
    }
});


