(function($){
    // plugin initialization
    $.transponder = function(o){
        
        // Initialize options
        var options = $.extend({
            appId : null,
            platform : null,
            serverUrl : null,
            state : null,
            params : {},
            view : 'canvas',
            fbPreview : false,
            appUrl : null,
            isPreview : false
        },o);
        
        $.transponder.getAppId = function() {
            return options.appId;
        }
        
        $.currentPlatform = function() {
            return options.platform;
        }
        
        $.isPreview = function() {
            return options.isPreview;      
        }
        
        // Return if facebook preview
        $.transponder.isFacebookPreview = function() {
            return options.fbPreview;
        };
        
        // Return server domain
        $.transponder.serverUrl = function() {
            return options.serverUrl;
        };
        
        // Return app url
        $.transponder.getAppUrl = function() {
            return options.appUrl;
        }
        
        // Prepend our server domain
        $.serviceCall = function(url, data, callback) {
            url = options.serverUrl+url;
            return $.get(url, data, callback, "json");
        };
        
        // Prepend our server domain
        $.servicePost = function(url, data, passcb, failcb) {
            if (!failcb) {
                failcb = passcb;
            }
            
            return $.ajax({
                url: options.serverUrl + url,
                data: data,
                dataType: 'json',
                type: 'POST',
                success: passcb,
                error: failcb
            });
        };
        
        // Prepend our server domain
        $.imageUrl = function(url) {
            return options.serverUrl+"/transponder/"+url;
        };
        
        // Prepend our server domain
        $.flashUrl = function(url) {
            return options.serverUrl+"/transponder/"+url;
        };
        
        // Registered function to fire later
        $.fn.tabInit = function(fn) {
            if ( $(this)[0].init === undefined ) {
                $(this)[0].init = fn;
            }
        };
        $.fn.tabActivate = function(fn) {
            if ( $(this)[0].activate === undefined ) {
                $(this)[0].activate = fn;
            }
        };
        
        // Find URL Param
        $.urlParam = function(name) {
            if (options.params[name]) {
                return options.params[name];
            }
            return null;
        };
        
        // All Url Params
        $.allUrlParams = function() {
            return options.params;
        };
        
        // Enter Fluid Mode
        $.fluidMode = function(){
            $(".content").css("height","auto");
        };
        
        // State
        $.setState = function(tabId,state,stateOptions) {
            tabId = tabId.replace("#","");
            options.state = tabId+"_"+state;
            $(document).data(tabId+"_state", state); // global state used by slider.js arrows
            var images = $(".imagetextitem");
            images.hide();
            for (var x=0;x<images.length;x++) {
                var image = $(images[x]);
                if (image.hasClass("view_"+options.view) || image.hasClass("view_all")) {
                    if (image.hasClass("alltabs")) { image.show(); }
                    if (image.hasClass(options.state)) { image.show(); }
                }
            }
        };
        
        $.currentTab = function() {
            if (options.state) {
                    return options.state.split("_")[0];
            }
            return null;
        }
        
        // Event Binding
        $.bindEvent = function(event,callback) {
            var images = $(".imagetextitem");
            for (var x=0;x<images.length;x++) {
                var image = $(images[x]);
                if (image.hasClass("event_"+event) && (image.hasClass(options.state) || image.hasClass("view_all"))) {
                    image.unbind("mousedown");
                    image.css("cursor","pointer");
                    image.bind("mousedown",function(){
                        return (callback(this) == true) ? true : false;
                    });
                }
            }
        };
        
        $.injectFBCDebugConsoleIfNeeded = function() {
            if (!$.urlParam('fbcdebug')) return;
            
            // prepare fbc debugging box because we are in fbc debug mode
            // easyXDM.Debug.trace(msg) will output its messages to any element with the id "log"
            document.write("Embed IFRAME domain: " + location.host);
            document.write('<div id="log" style="height:100px;border:1px dotted black;overflow:auto"></div>');
            document.write('<input type="button" onclick="$.remote.alertMessage(\'message from remote\');" value="call alertMessage on local domain"/>');
        };

        $.loadFBCSupportIfNeeded = function() {
            if (!$.urlParam('fbc')) return;
            
            var inDebugMode = $.urlParam('fbcdebug')?'.debug':'';
            document.write('<scr'+'ipt type="text/javascript" src="/transponder/easyxdm/easyXDM'+inDebugMode+'.js"></scr'+'ipt>');
            // this line is not needed because we are already loading json2, uncomment when situation changes
            // document.write('<scr'+'ipt type="text/javascript">easyXDM.DomHelper.requiresJSON("/transponder/easyxdm/json2.js");</scr'+'ipt>');
        };
        
        $.initFBCSupportIfNeeded = function() {
            if (!$.urlParam('fbc')) return;

            var callbackMap = {}; // here I store all pending callback functions which are waiting to be called
            var callbackCounter = 0; // cast assigned callback id
            
            // init fbc support (via easyXDM) when requested
            var channel = {};
            var interfaces = {
                // this is interface expected to be implemented on the hosting page (the parent of our IFRAME)
                remote: {
                    alertMessage: {
                        isVoid: true
                    },
                    streamPublishInternal: {
                        isVoid: true
                    }
                },
                // this is interface our IFRAME provides to the hosting page
                local: {
                    streamPublishCallback: {
                        method: function(cid/*, arg0, arg1, ... */) {
                            // map callbackId back to callback function and call it with original params
                            var callback = callbackMap[cid];
                            if (callback) {
                                delete callbackMap[cid];
                                var args = $.makeArray(arguments);
                                args.shift();
                                callback.apply(this, args);
                            }
                        },
                        isVoid: true
                    },
                    testMe: {
                        isVoid: true,
                        method: function(){
                            alert("Test method");
                        }
                    }
                }
            };
            // when the channel is ready we create the interface
            $.remote = new easyXDM.Interface(channel, interfaces);
            
            // we need to deal with callbacks, translate callbacks <-> ids when crossing FRAME boundary
            $.remote.streamPublish = function(userMessage, attachment, actionLinks, targetId, userMessagePrompt, callback, autoPublish, actorId) {
                if (!callback) {
                    return $.remote.streamPublishInternal(userMessage, attachment, actionLinks, targetId, userMessagePrompt, 0, autoPublish, actorId); // zero callbackId means "no callback"
                }
                callbackCounter++;
                callbackMap[callbackCounter] = callback;
                return $.remote.streamPublishInternal(userMessage, attachment, actionLinks, targetId, userMessagePrompt, callbackCounter, autoPublish, actorId);
            };
        };
        
        // this function is responsible for initializing touch-scrollable components in the page
        // as you can see, it is safe to call this function multiple times
        // usually you want to call it every time you render new touch scrollable area or when content of touch-scrollable area changes
        $.initTouchScrollers = function() {
            var platform = $.currentPlatform();
            if (!(platform=='iphone' || platform=='android')) return;
            if (typeof iScroll == 'undefined') return;
            // init all iscroll guys
            $('.pane').css('height', '100%'); // wrapper needs to have real height for iscroll to init correctly
            $('.pane').css('width', '100%');
            $(".iscroll").each(function() {
                // read http://cubiq.org/scrolling-div-on-iphone-ipod-touch/5 (or latest doc when available)
                var scroller = $(this);
                if (!scroller.hasClass('iscroll-applied')) {
                    scroller.addClass('iscroll-applied'); // height of the scroller should be dynamic and adapted to the content
                    var wrapper = scroller.parent();
                    wrapper.css({
                        'position': 'relative',
                        'z-index': 1
                    });
                    var iscroll = new iScroll(this, scroller.attr('iscroll-scrollbars'));
                    scroller.data('iscroll', iscroll); // for programatic manipulation, may be handy for using scrollTo()
                }
            });
        }
    };
})(jQuery);