/**
 * Club Create CMS Core JavaScript Functions
 *
 * CC.util - Generic Utility Functions
 * CC.api - API Access Layer
 * CC.tmpl - Template Management
 * CC.auth - User Management
 * CC.pages - Page 'Controllers'
 * CC.init - Initialization
 * CC.data - Random Data Cache
 * misc - some misc carry over functions
 */

/**
 * TODO:
 *
 * Form validation
 * Request error handling
 * move page paths out of file
 * hook up unauthorized/login overlay
 * content loading indicators
 */

(function ($) {

    window.CC = window.CC || {};

    // Generic Utility Functions
    window.CC.util = {
        // key for lookup in query string, if href blank use URL
        getQueryStringVal: function (key, href) {
            href = (!href) ? window.location.href : href;
            var results = new RegExp('[\\?&]' + key + '=([^&#]*)').exec(href);
            if (results) {
                return results[1];
            } else {
                return null;
            }
        },
        sanitize: function (val) {
            return encodeURIComponent(val);
        },
        getString: function (msg) {
            if ((typeof STRINGS !== 'undefined') && (typeof STRINGS[msg] !== 'undefined')) {
                return STRINGS[msg];
            }
            return "";
        },
        serializedArrayToReqJSON: function (serializedArray) { // Flatten $.seriailzeArray() output a bit & JSONify
            var reqData = {};
            if (serializedArray && serializedArray.length) {
                $.each(serializedArray, function (i, field) {
                    reqData[field.name] = field.value;
                });
            }
            //return $.toJSON(reqData);
            return reqData;
        },
        getBitmaskValue: function(dectotal,decmask) {
            var mask = parseInt(decmask.toString()),
            total= parseInt(dectotal.toString());
            return ((total & mask) == mask);
        },
        popWindow: function( url, width, height ) {
            var  screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
            screenY      = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
            outerWidth   = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.body.clientWidth,
            outerHeight  = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.body.clientHeight - 22),
            left         = parseInt(screenX + ((outerWidth - width) / 2), 10),
            top          = parseInt(screenY + ((outerHeight - height) / 2.5), 10);
            var features = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top;

            var newwindow = window.open(url, false, features);
            if( window.focus ) {
                newwindow.focus();
            }
        },
        refreshImage: function(selector) {
            $(selector).each(function() {
                var $this = $(this);
                var src = $this.attr('src');
                if(src == undefined) return;

                // For some reason, ff ignores setting src via $.attr()
                var img = $this.get(0);

                // Find out if there are any params
                if(src.indexOf('?') == -1) {
                    img.src = src + '?c=' + Number(new Date());
                } else {
                    if(src.indexOf('c=') == -1) {
                        img.src = src + '&c=' + Number(new Date());
                    } else {
                        img.src = src.replace(/c=\d*/, 'c=' + Number(new Date()));
                    }
                }
            });
        },
        debug: function(msg) {
            if(window.console && window.console.log) {
                window.console.log(msg);
            }
        },
        parseDate: function(timestamp) {
            //function parses mysql datetime string and returns javascript Date object
            //input has to be in this format: 2007-06-05 15:26:02
            var regex=/^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9]) (?:([0-2][0-9]):([0-5][0-9]):([0-5][0-9]))?$/;
            var parts = timestamp.replace(regex,"$1 $2 $3 $4 $5 $6").split(' ');
            return new Date(parts[0],parts[1] - 1,parts[2],parts[3],parts[4],parts[5]);
        }
    };

    // API Access Layer
    window.CC.api = {
        baseurl: "http://api.clubcreate.com",
        settings: {
            genres: function(params,callback,error) {
                var reqpath = "/settings/genres/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            instruments: function(params,callback,error) {
                var reqpath = "/settings/instruments/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            keys: function(params,callback,error) {
                var reqpath = "/settings/keys/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            rights: function(params,callback,error) {
                var reqpath = "/settings/rights/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            tools: function(params,callback,error) {
                var reqpath = "/settings/tools/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        user: {
            info: function(params,callback,error) {
                var reqpath = "/user/info/" + (params.username || '') + '/' + (params.view || ''),
                    reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/user/update.cors",
                    reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/user/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            favorites: function(params, callback,error) {
                var reqpath = "/user/favorites/{username}/{page:1}/{pageSize:10}.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addfavorite: function(params,callback,error) {
                var reqpath = "/user/addfavorite/" + params.uuid + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removefavorite: function(params,callback,error) {
                var reqpath = "/user/removefavorite/" + params.uuid + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addfan: function(params,callback,error) {
                var reqpath = "/user/becomefanof/" + params.username + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removefan: function(params,callback,error) {
                var reqpath = "/user/stopbeingfanof/" + params.username + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            authenticate: function(params, callback, error) {
                var reqpath = '/user/authenticate',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = '/user/create.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            lostpassword: function(params,callback,error) {
                var reqpath = '/user/lostpassword.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            resetpassword: function(params,callback,error) {
                var reqpath = '/user/resetpassword/' + params.token + '.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            changepassword: function(params,callback,error) {
                var reqpath = '/user/changepassword.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            verify: function(params,callback,error) {
                var reqpath = '/user/verify/' + params.username + ( params.token ? '/' + params.token : '' ) + '.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            comments: function(params,callback,error) {
                var reqpath = "/user/comments/"+ params.username + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            commenton: function(params,callback,error) {
                var reqpath = "/user/commenton/" + params.username,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removecomment: function(params,callback,error) {
                var reqpath = "/user/removecomment/{username}/{uuid}",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            cancelaccount: function(params,callback,error) {
                var reqpath = "/user/cancelaccount.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        users: {
            likedBy: function(params,callback,error) {
                var reqpath = "/users/likedby/{username}/{page:1}/{pageSize:12}.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            fansOf: function(params,callback,error) {
                var reqpath = "/users/fansof/{username}/{page:1}/{pageSize:12}.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            favoriteOf: function(params,callback,error) {
                var reqpath = '/users/favoriteof/{uuid}/{page:1}/{pageSize:10}.cors',
                reqmethod = 'GET';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        storage: {
            contents: function(params,callback,error) {
                var reqpath = '/storage/contents.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            describe: function(params,callback,error) {
                var reqpath = '/storage/describe.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            remove: function(params,callback,error) {
                var reqpath = '/storage/remove.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            url: function(params,callback,error) {
                var reqpath = '/storage/url/' + (params.redirect || '') +'.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            upload: function(params,callback,error) {
                var reqpath = '/storage/upload.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        dropbox: {
            create: function(params,callback,error) {
                var reqpath = '/dropbox/create.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/dropbox/find/{pattern:all}/{page:1}/{pageSize:10}.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            remove: function(params,callback,error) {
                var reqpath = '/dropbox/delete/{uuid}.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        campaign: {
            info: function(params,callback,error) {
                var reqpath = "/campaign/info/" + params.uuid,
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/campaign/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            autocomplete: function(params,callback,error) {
                var reqpath = "/campaign/autocomplete/" + (params.pattern) + '/' + (params.size || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = "/campaign/create/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/campaign/update/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            setimage: function(params) {
                var reqpath = "/campaign/setimage/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod);
            },
            addstudio: function(params,callback,error) {
                var reqpath = "/campaign/addstudio/" + params.campaign_uuid + "/" + params.studio_uuid + '.cors',
                reqmethod = "POST";
                delete params.campaign_uuid;
                delete params.studio_uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removestudio: function(params,callback,error) {
                var reqpath = "/campaign/removestudio/" + params.campaign_uuid + "/" + params.studio_uuid + '.cors',
                reqmethod = "POST";
                delete params.campaign_uuid;
                delete params.studio_uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            setcost: function(params,callback,error) {
                var reqpath = "/campaign/setcost/" + params.campaign_uuid + "/" + (params.cost_uuid || ''),
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removecost: function(params,callback,error) {
                var reqpath = "/campaign/removecost/" + params.campaign_uuid + "/" + params.cost_uuid,
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        library: {
            info: function(params,callback,error) {
                var reqpath = "/cmpn_library/info/" + params.uuid + '/' + ( params.full ? '/full' : '') + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = "/cmpn_library/create.cors",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/cmpn_library/update/" + params.uuid + '.cors',
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            duplicate: function(params,callback,error) {
                var reqpath = "/cmpn_library/duplicate/" + params.uuid + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            del: function(params,callback,error) {
                var reqpath = "/cmpn_library/delete/" + params.uuid + '.cors',
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/cmpn_library/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            autocomplete: function(params,callback,error) {
                var reqpath = "/cmpn_library/autocomplete/" + (params.pattern) + '/' + (params.size || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addasset: function(params,callback,error) {
                var reqpath = "/cmpn_library/addasset/" + params.library_uuid + "/" + params.asset_uuid + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removeasset: function(params,callback,error) {
                var reqpath = "/cmpn_library/removeasset/" + params.library_uuid + "/" + params.asset_uuid + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        studio: {
            info: function(params,callback,error) {
                var reqpath = "/studio/info/" + params.uuid,
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/studio/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            autocomplete: function(params,callback,error) {
                var reqpath = "/studio/autocomplete/" + (params.pattern) + '/' + (params.size || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = "/studio/create/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/studio/update/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            setimage: function(params) {
                var reqpath = "/studio/setimage/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,null,{},null);
            },
            setsocial: function(params,callback,error) {
                var reqpath = "/studio/setsocial/" + params.studio_uuid + "/" + params.service,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            setsocialimage: function(params,callback,error) {
                var reqpath = "/studio/setsocialimage/" + params.studio_uuid + "/" + params.service,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addlibrary: function(params,callback,error) {
                var reqpath = "/studio/addlibrary/"  + params.studio_uuid + "/" + params.library_uuid + '/' + (params.type || 'default') + '.cors',
                reqmethod = "POST";
                delete params.studio_uuid;
                delete params.library_uuid;
                delete params.type;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removelibrary: function(params,callback,error) {
                var reqpath = "/studio/removelibrary/" + params.studio_uuid + "/" + params.library_uuid + '/' + (params.type || 'default') + '.cors',
                reqmethod = "POST";
                delete params.studio_uuid;
                delete params.library_uuid;
                delete params.type;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addsong: function(params,callback,error) {
                var reqpath = '/studio/addsong/' + params.studio_uuid + '/' + params.song_uuid,
                reqmethod = 'GET';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removesong: function(params,callback,error) {
                var reqpath = '/studio/removesong/' + params.studio_uuid + '/' + params.song_uuid,
                reqmethod = 'GET';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            createsession: function(params,callback,error) {
                var reqpath = '/studio/createsession/{uuid}.cors',
                reqmethod = 'POST';
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        legacy_asset: {
            upload: function(params,callback,error) {
                var reqpath = "/asset/upload/" + (params.chunks || '0') + '/' + (params.trusted || ''),
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            processupload: function(params,callback,error) {
                var reqpath = "/asset/processupload/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        asset: {
            info: function(params,callback,error) {
                var reqpath = "/cmpn_asset/info/" + params.uuid + '/' + (params.view || '') + '.cors',
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = "/cmpn_asset/create",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/cmpn_asset/update/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/cmpn_asset/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            autocomplete: function(params,callback,error) {
                var reqpath = "/cmpn_asset/autocomplete/" + (params.pattern) + '/' + (params.size || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            upload: function(params,callback,error) {
                var reqpath = "/cmpn_asset/upload/" + params.uuid + '/' + (params.chunks || '0') + '/' + (params.trusted || ''),
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            processupload: function(params,callback,error) {
                var reqpath = "/cmpn_asset/processupload/" + params.uuid + '/' + params.key,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            exportAssets: function(params,callback,error) {
                var reqpath = "/cmpn_asset/export/" + (params.mode || 'full') + '.cors',
                reqmethod = "POST";
                delete params.mode;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addrightsholder: function(params,callback,error) {
                var reqpath = "/cmpn_asset/addrightsholder/" + params.uuid + '/' + params.group + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                delete params.group;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removerightsholder: function(params,callback,error) {
                var reqpath = "/cmpn_asset/removerightsholder/" + params.uuid + '/' + params.group + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                delete params.group;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            rightsholders: function(params,callback,error) {
                var reqpath = "/cmpn_asset/rightsholders/" + params.pattern + '.cors',
                reqmethod = "POST";
                delete params.pattern;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            comments: function(params,callback,error) {
                var reqpath = "/cmpn_asset/comments/{uuid}/{page:1}/{pageSize:10}.cors",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            commenton: function(params,callback,error) {
                var reqpath = "/cmpn_asset/commenton/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removecomment: function(params,callback,error) {
                var reqpath = "/cmpn_asset/removecomment/{uuid}",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        session: {
            info: function(params,callback,error) {
                var reqpath = "/session/info/" + params.uuid,
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/session/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                delete params.pattern;
                delete params.page;
                delete params.pageSize;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        draft: {
            info: function(params,callback,error) {
                var reqpath = "/draft/info/" + params.uuid,
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/draft/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                delete params.pattern;
                delete params.page;
                delete params.pageSize;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            url: function(params,callback,error) {
                var reqpath = "/draft/url/" + params.tool + '/' + params.uuid + '/' + params.action + '/' + (params.redirect || '') + (params.extension || ''),
                reqmethod = "GET",
                opt = {
                    dataType: params.dataType || 'xml'
                };
                delete params.tool;
                delete params.uuid;
                delete params.action;
                delete params.redirect;
                delete params.extension;
                delete params.dataType;
                return CC.api.fetch(reqpath,reqmethod,params,callback,opt,error);
            },
            save: function(params,callback,error) {
                var reqpath = "/draft/save/" + params.tool + '/' + params.mode + '/' + params.uuid,
                reqmethod = "POST",
                opt = {
                    dataType: params.dataType || 'xml'
                };
                delete params.tool;
                delete params.uuid;
                delete params.mode;
                return CC.api.fetch(reqpath,reqmethod,params,callback,opt,error);
            },
            visibility: function(params,callback,error) {
                var reqpath = "/draft/visibility/" + params.uuid + '/' + params.mode,
                reqmethod = "GET";
                delete params.uuid;
                delete params.mode;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        resource: {
            get: function(params,callback,error) {
                var reqpath = "/resource/get",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{dataType: 'text'},error);
            }
        },
        song: {
            info: function(params,callback,error) {
                var reqpath = "/song/info/" + params.uuid,
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/song/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            comments: function(params,callback,error) {
                var reqpath = "/song/comments/"+ params.uuid + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            commenton: function(params,callback,error) {
                var reqpath = "/song/commenton/" + params.uuid,
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removecomment: function(params,callback,error) {
                var reqpath = "/song/removecomment/{username}/{uuid}",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            vote: function(params,callback,error) {
                var reqpath = "/song/vote/" + params.uuid + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        facebook: {
            sharetimestamp: function(params,callback,error) {
                var reqpath = "/facebook/sharetimestamp/" + params.uuid + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            syncpicture: function(params,callback,error) {
                var reqpath = "/facebook/syncpicture.cors",
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            unlink: function(params,callback,error) {
                var reqpath = "/facebook/unlink.cors",
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        twitter: {
            sharetimestamp: function(params,callback,error) {
                var reqpath = "/twitter/sharetimestamp/" + params.uuid + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            syncpicture: function(params,callback,error) {
                var reqpath = "/twitter/syncpicture.cors",
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            unlink: function(params,callback,error) {
                var reqpath = "/twitter/unlink.cors",
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        email: {
            sharetimestamp: function(params,callback,error) {
                var reqpath = '/email/sharetimestamp/' + params.uuid + '.cors',
                reqmethod = 'POST';
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        marketplace: {
            info: function(params,callback,error) {
                var reqpath = "/marketplace/info/" + params.uuid,
                reqmethod = "GET";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            find: function(params,callback,error) {
                var reqpath = "/marketplace/find/" + (params.pattern || 'all') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                delete params.pattern;
                delete params.page;
                delete params.pageSize;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            autocomplete: function(params,callback,error) {
                var reqpath = "/marketplace/autocomplete/" + (params.pattern || 'all') + "/" + (params.length || '10') + '.cors',
                reqmethod = "GET";
                delete params.pattern;
                delete params.length;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = "/marketplace/create.cors",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            update: function(params,callback,error) {
                var reqpath = "/marketplace/update/" + params.uuid + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            addcontent: function(params,callback,error) {
                var reqpath = "/marketplace/addcontent/" + params.product_uuid + '/' + params.type + '/' + params.item_uuid + '.cors',
                reqmethod = "POST";
                delete params.product_uuid;
                delete params.type;
                delete params.item_uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            removecontent: function(params,callback,error) {
                var reqpath = "/marketplace/removecontent/" + params.product_uuid + '/' + params.type + '/' + params.item_uuid + '.cors',
                reqmethod = "POST";
                delete params.product_uuid;
                delete params.type;
                delete params.item_uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            purchase: function(params,callback,error) {
                var reqpath = "/marketplace/purchase/" + params.uuid + '.cors',
                reqmethod = "POST";
                delete params.uuid;
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        promo: {
            register: function(params,callback,error) {
                var reqpath = '/promo/register.cors',
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            create: function(params,callback,error) {
                var reqpath = '/promo/create.cors',
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            generate: function(params,callback,error) {
                var reqpath = '/promo/generate.cors',
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        locker: {
            products: function(params,callback,error) {
                var reqpath = "/locker/products/" + (params.username || 'me') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            libraries: function(params,callback,error) {
                var reqpath = "/locker/libraries/" + (params.username || 'me') + "/" + (params.page || '1') + "/" + (params.pageSize || '10'),
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        xml: {
            fragments: function(params,callback,error) {
                var reqpath = "/xml/fragments/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            fragment: function(params,callback,error) {
                var reqpath = "/xml/fragment/",
                reqmethod = "GET";
                return CC.api.fetch(reqpath,reqmethod,params,callback, {
                    dataType: 'text'
                }, error);
            },
            removefragment: function(params,callback,error) {
                var reqpath = "/xml/removefragment/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            },
            setfragment: function(params,callback,error) {
                var reqpath = "/xml/setfragment/",
                reqmethod = "POST";
                return CC.api.fetch(reqpath,reqmethod,params,callback,{},error);
            }
        },
        fetch: function(reqpath, reqmethod, reqdata, callback, optoverride, errorCallback) {
            // Build the request path
            // This replaces elements in the url according to the format
            // {reqdata param:default value}
            reqpath = reqpath.replace(/\{\{|\}\}|\{([^}: ]+?)(?::([^}]*?))?\}/g, function(match, name, def) {
                if (match == "{{") {
                    return "{";
                } else if (match == "}}") { 
                    return "}"; 
                }
                if(typeof reqdata[name] != 'undefined') {
                    var v = reqdata[name];
                    delete reqdata[name];
                    return encodeURIComponent(v);
                } else if(typeof def != 'undefined') {
                    return def;
                } else {
                    return '';
                }
            });
            
            // build request options
            var opts = $.extend({},CC.api.reqdefaults,{
                url: CC.api.baseurl+reqpath,
                type: reqmethod,
                data: reqdata
            },optoverride);

            opts.success = function(res) {
                if($(res).children('error').length != 0) {
                    if($.isFunction(errorCallback)) {
                        var error = $(res).find('error');
                        errorCallback(res, parseInt(error.attr('response_code')), error.attr('message_key'));
                    }
                } else if($.isFunction(callback)) {
                    callback(res);
                }
            };
            
            // massage the request object (via existing code)

            // Token??
            var token = $.getCookie('clubcreate');
            if (opts.useToken != false && token) {
                opts.data.t = token;
            }

            // cachebust gets??
            if ("GET" == opts.type.toUpperCase()) {
                opts.data.c = "c"+Number(new Date());
            }
            
            // Set our error handler
            opts.error = function(xhr, status, err) {
                if($.isFunction(errorCallback)) {
                    errorCallback(xhr, status, err);
                }

                // TODO: find a way to properly get the status code from the request
                if (xhr.responseText) {
                    CC.util.debug('Unidentified request error: ' + status + ' - ' + err);
                }
            };

            // work IE
            if ('xdr' == this.xhr) {
                opts.xhr = function() {
                    var xdr = new XDomainRequest();
                    xdr.onload = function() {
                        if (xdr.contentType.match(/\/xml/)){
                            // there is no responseXML in XDomainRequest, so we have to create it manually
                            var dom = new ActiveXObject('Microsoft.XMLDOM');
                            dom.async = false;
                            dom.loadXML(xdr.responseText);
                            opts.success(dom);
                        } else {
                            opts.success(this.responseText); // we will assume that the status code is 200, XDomainRequest rejects all other successful status codes
                        // see bug https://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=334804
                        }
                    };
                    xdr.onerror = function() {
                        opts.error(this);
                    }
                    xdr.ontimeout = function() {
                        opts.error(this);
                    }
                    return xdr;
                }
            } else if('flxhr' == this.xhr) {
                // Set the xhr handler
                opts.xhr = function() {
                    return new flensed.flXHR({
                        instancePooling: false,
                        onerror: function(err) {
                            try {
                                err.srcElement.readyState = 4;
                            } catch(e) {}
                            opts.error.apply(opts, arguments);
                        }
                    });
                };
                
                // See if the modules ready
                try {
                    flensed.flXHR.module_ready();
                } catch(err) {
                    if(!this.requestBuffer) {
                        this.requestBuffer = [];
                        var self = this;
                        this.requestBufferInterval = window.setInterval(function() {
                            try {
                                flensed.flXHR.module_ready();
                                window.clearInterval(self.requestBufferInterval);
                                $(self.requestBuffer).each(function() {
                                    $.ajax(this);
                                });
                            } catch(err) {
                            }
                        }, 200);
                    }
                    this.requestBuffer.push(opts);
                    return null;
                }
            }

            // kick off ajax request
            return $.ajax(opts);
        },
        // defaults taken from existing code
        reqdefaults: {
            useToken: true,
            data: {},
            type: "GET",
            dataType: "xml"
        },
        xhr: 'xhr',
        init: function() {
            var self = this;
            var embedFlensed = function() {
                // embed the flXHR script for cors support
                var loadScript = function(url) {
                    var script = document.createElement('script');
                    script.async = false;
                    script.type = 'text/javascript';
                    script.src = url;
                    document.getElementsByTagName('head')[0].appendChild(script);
                }

                window.flensed = {
                    base_path: 'http://static.clubcreate.com/js/flxhr/'
                };
                loadScript('http://static.clubcreate.com/js/flxhr/flXHR.js');
                
                if($.ajaxPrefilter) {
                    $.ajaxPrefilter( function( options ) {
                        options.crossDomain = false;
                    });

                }
                self.xhr = 'flxhr';
            }
            
            if(typeof(XDomainRequest) != 'undefined') {
                if($.ajaxTransport) {
                    this.xhr = 'transport';
                    $.ajaxTransport( function( options, originalOptions, jqXHR ) {
                        var xdr;

                        return {
                            send: function( _, completeCallback ) {
                                xdr = new XDomainRequest();
                                xdr.onload = function() {
                                    var responses = {
                                        text: xdr.responseText
                                    };

                                    if (xdr.contentType.match(/\/xml/)){
                                        // there is no responseXML in XDomainRequest, so we have to create it manually
                                        var dom = new ActiveXObject('Microsoft.XMLDOM');
                                        dom.async = false;
                                        dom.loadXML(xdr.responseText);
                                        responses.xml = dom;

                                        if($(dom).children('error').length != 0) {
                                            var $error = $(dom).find('error');
                                            completeCallback(parseInt($error.attr('response_code')), $error.attr('message_key'), responses);
                                        } else {
                                            completeCallback(200, 'success', responses);
                                        }

                                    } else {
                                        completeCallback(200, 'success', responses); // we will assume that the status code is 200, XDomainRequest rejects all other successful status codes
                                    // see bug https://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=334804
                                    }
                                };
                                xdr.onerror = xdr.ontimeout = function() {
                                    var responses = {
                                        text: xdr.responseText
                                    };
                                    completeCallback(400, 'failed', responses);
                                }

                                xdr.open(options.type, options.url);
                                xdr.send(options.data);
                            },
                            abort: function() {
                                if(xdr) {
                                    xdr.abort();
                                }
                            }
                        };
                    });
                } else {
                    this.xhr = 'xdr';
                }
            } else if(!$.support.ajax || !$.support.cors) {
                embedFlensed();
            }
        }
    };

    $(document).ready(function() {
        CC.api.init();
    });

    window.CC.data = {};
})(jQuery);

// copy+past from user code base
(function($) {
    $.setCookie = function(name, value, days, domain) {
        var expires = "";
        if (typeof(days) != 'undefined') {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            expires = "; expires="+date.toGMTString();
        }
        var d = '';
        if(domain) {
            d = '; domain=' + domain;
        }
        document.cookie = name+"="+value+expires+"; path=/" + d;
    };

    $.getCookie = function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    };

    $.deleteCookie = function(name, domain) {
        $.setCookie(name, '', -1, domain);
    };
})(jQuery);
