$.Class('Tacky', {
    init: function() {
        this.currentSite = this.site(parseInt($('meta[name=siteId]').attr('content'), 10));
        this.currentContentPool = this.getContentPool();
        this.seturlParams();
        this.setupGoogleAnalytics();
    },
    currentSite: null,
    currentContentPool: undefined,
    adViewTimeout: null,
    urlParams: {},
    sites: [{
        id: 1,
        languageid: 3,
        country: 'NO',
        language: 'nb',
        analytics: 'UA-292387-1',
        twitter: {
            search: 'from:tackyDOTno OR @tackyDOTno',
            title: '@tackyDOTno'
        },
        facebook: {
            url: 'http://www.facebook.com/pages/Tackyno/199364500075087'
        }
    }, {
        id: 2,
        languageid: 1,
        analytics: 'UA-292387-4'
    }, {
        id: 3,
        languageid: 4,
        analytics: 'UA-292387-2',
        facebook: {
            url: 'http://www.facebook.com/TackySverige'
        }
    }, {
        id: 4,
        languageid: 5,
        analytics: 'UA-292387-3',
        facebook: {
            url: 'http://www.facebook.com/pages/Tackydk/172575866126708'
        }
    }, {
        id: 5,
        languageid: 10,
        analytics: 'UA-292387-13',
        facebook: {
            url: 'http://www.facebook.com/pages/Tacky-World-UK/154475657931055'
        }
    }, {
        id: 7,
        languageid: 12,
        analytics: 'UA-292387-10',
        facebook: {
            element: '#news',
            method: 'before',
            url: 'http://www.facebook.com/tacky.polska'
        }
    }, {
        id: 8,
        languageid: 13,
        analytics: 'UA-292387-5',
        twitter: {
            search: 'from:TackyNederland OR @TackyNederland',
            title: '@TackyNederland'
        },
        facebook: {
            url: 'http://www.facebook.com/pages/Tacky-Nederland/134781396538755'
        }
    }, {
        id: 9,
        languageid: 6,
        analytics: 'UA-292387-7'
    }, {
        id: 10,
        languageid: 17,
        analytics: 'UA-292387-11',
        twitter: {
            element: '#facebookLikeHolder',
            method: 'before',
            options: {
                search: 'from:tackyfi OR @tackyfi',
                title: '@tackyfi'
            }
        },
        facebook: {
            element: '#poll',
            method: 'before',
            url: 'http://www.facebook.com/TackySuomi'
        }
    }, {
        id: 13,
        languageid: 18,
        analytics: 'UA-292387-12',
        facebook: {
            url: 'http://www.facebook.com/pages/Tackyfr/218768262999'
        }
    }, {
        id: 14,
        languageid: 19,
        analytics: 'UA-292387-15'
    }],
    site: function(id) {
        for (var i = 0; i < this.sites.length; i++) {
            if (this.sites[i].id === id) {
                return this.sites[i];
            }
        }
        return null;
    },
    trackVirtualPageView: function(relativeUrl) {
        if (relativeUrl === undefined) return;
        var pageTracker = _gat._getTracker(this.currentSite.analytics);
        pageTracker._trackEvent('AjaxEveryClickPageview', relativeUrl);

        clearTimeout(this.AdViewTimeout);
        this.adViewTimeout = setTimeout(function() {
            pageTracker._trackPageview(relativeUrl);
            pageTracker._trackEvent('AjaxActualRecordedPageview', relativeUrl);

            var iframes = $('iframe[src*="openads"]');
            var src = [];

            iframes.each(function(i) {
                src[i] = $(this).attr('src');
            });

            $('iframe[src*="openads"]').attr('src', '');

            iframes.each(function(i) {
                $(this).attr('src', src[i]);
            });
        }, 1500);
    },
    trackOutboundLink: function(source, link) {
        if (link === undefined || link === null) return;
        var pageTracker = _gat._getTracker(this.currentSite.analytics);
        pageTracker._trackEvent('OutboundLink', source, link);
    },
    seturlParams: function() {
        var e, a = /\+/g,
            // Regex for replacing addition symbol with a space
            r = /([^&;=]+)=?([^&;]*)/g,
            d = function(s) {
                return decodeURIComponent(s.replace(a, " "));
            },
            q = window.location.search.substring(1);

        while (e = r.exec(q)) Tacky.urlParams[d(e[1])] = d(e[2]);
    },
    getContentPool: function() {
        if (document.location.pathname.split('/').length < 2) return null;

        var skateboardSection = 'skateboard';
        var snowboardSection = 'snowboard';
        var surfSection = 'surf';

        switch (document.location.pathname.split('/')[1]) {
        case skateboardSection:
            return skateboardSection;
        case snowboardSection:
            return snowboardSection;
        case surfSection:
            return surfSection;
        default:
            return null;
        }
    },
    ads: {
        background: function(image, link, backgroundColor) {
            $('<a href="' + link + '" target="_blank" class="adleft"></a>').appendTo('body');
            $('<a href="' + link + '" target="_blank" class="adright"></a>').appendTo('body');
            Tacky.ads.resizeBackgroundClickArea();

            $('html, body').css({
                backgroundImage: 'url(' + image + ')',
                backgroundColor: backgroundColor,
                backgroundRepeat: 'no-repeat',
                backgroundPosition: 'top center'
            });

            $(window).resize(function() {
                Tacky.ads.resizeBackgroundClickArea();
            });
        },
        resizeBackgroundClickArea: function() {
            var outerw = $('#outerw');
            var left = outerw.offset().left;
            var right = left + 990;

            if (left > 0) {
                $('.adleft').width(left);
                $('.adright').width($(window).width() - right);
            } else {
                $('.adleft').width(0);
                $('.adright').width(0);
            }
        }
    },
    setupExternal: function() {
        var self = this;
        //Take a second to load facebook/twitter etc
        setTimeout(function() {
            self.setupFacebook();
            self.setupTwitter();
        }, 100);
    },
    setupGoogleAnalytics: function() {
        var _gaq = _gaq || [];
        _gaq.push(['_setAccount', Tacky.currentSite.analytics]);
        _gaq.push(['_trackPageview']);

        (function() {
            var ga = document.createElement('script');
            ga.type = 'text/javascript';
            ga.async = true;
            ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(ga, s);
        })();

        function recordOutboundLink(link, category, action) {
            try {
                var pageTracker = _gat._getTracker(Tacky.currentSite.analytics);
                pageTracker._trackEvent(category, action);
                setTimeout('document.location = "' + link.href + '"', 100);
            } catch (err) {}
        }
    },
    setupFacebook: function() {
        if (Tacky.currentSite.facebook === undefined) return;
        var element = Tacky.currentSite.facebook.element === undefined ? '#news' : Tacky.currentSite.facebook.element;
        var method = Tacky.currentSite.facebook.method === undefined ? 'after' : Tacky.currentSite.facebook.method;
        $(element)[method]('<div id="facebookLikeHolder" style="border-right: solid 1px #aaa; overflow: hidden; width: 180px; position: relative; left: -1px;"><fb:like-box href="' + Tacky.currentSite.facebook.url + '" connections="9" stream="false" header="false" width="182" height="430"></fb:like-box>');
        if (this.FB !== undefined) FB.XFBML.parse(document.getElementById('faceobokLikeHolder'));
    },
    setupTwitter: function() {
        $.getScript('http://widgets.twimg.com/j/2/widget.js', function() {
            if (Tacky.currentSite.twitter !== undefined) {

                var element = Tacky.currentSite.twitter.element === undefined ? '#news' : Tacky.currentSite.twitter.element;
                var method = Tacky.currentSite.twitter.method === undefined ? 'after' : Tacky.currentSite.twitter.method;

                $(element)[method]('<div id="twitterWidget"></div>');
                $('#twitterWidget').show();

                //default options
                var opt = {
                    version: 2,
                    type: 'search',
                    search: '',
                    interval: 8000,
                    title: '',
                    subject: '',
                    width: 180,
                    height: 600,
                    id: 'twitterWidget',
                    theme: {
                        shell: {
                            background: '#8ec1da',
                            color: '#ffffff'
                        },
                        tweets: {
                            background: '#ffffff',
                            color: '#444444',
                            links: '#1985b5'
                        }
                    },
                    features: {
                        scrollbar: true,
                        loop: false,
                        live: true,
                        hashtags: true,
                        timestamp: true,
                        avatars: true,
                        toptweets: false,
                        behavior: 'all'
                    }
                };

                //Default to simple options setting
                var options = Tacky.currentSite.twitter.options === undefined ? Tacky.currentSite.twitter : Tacky.currentSite.twitter.options;

                $.each(opt, function(i, v) {
                    $.each(options, function(x, value) {
                        if (i === x) {
                            opt[i] = value;
                        }
                    });
                });

                new TWTR.Widget({
                    version: opt.version,
                    type: opt.type,
                    search: opt.search,
                    interval: opt.interval,
                    title: opt.title,
                    subject: opt.subject,
                    width: opt.width,
                    height: opt.height,
                    theme: opt.theme,
                    features: opt.features,
                    id: opt.id
                }).render().start();

            }

        });
    }
}, {});



$.Class('Tacky.Service', {
    init: function() {
        jQuery.ajaxSettings.traditional = true; //Set default jquery ajax behaviour to play nicely with asp.net MVC  
    },
    defaultOptions: {
        success: this.success,
        error: this.error,
        async: true
    },
    jsonPostOptions: {
        success: this.success,
        error: this.error,
        async: true,
        type: 'POST',
        contentType: 'application/json; charset=utf-8'
    },
    json: function(params) {
        this.ajax(params);
    },
    ajax: function(options) {
        var self = this;
        //check if some required options are supplied
        //like url, and method, or just assume some, like get, etc
        var opt = $.extend({}, this.defaultOptions, options);
        opt.success = function(data) {
            self.success(data, options.success)
        };
        opt.error = function() {
            //Add the callback to the arguments before calling the internal error handling
            var args = Array.prototype.slice.apply(arguments);
            args.push(options.error);
            self.error.apply(this, args)
        };
        //if(!o.url) throw 'An url needs to be specified';
        $.ajax(opt);
    },
    postJSON: function(options) {
        var opt = $.extend({}, this.jsonPostOptions, options);
        opt.data = JSON.stringify(opt.data);
        this.ajax(opt);
    },
    success: function(data, callback) {
        callback(data);
    },
    error: function(jqXHR, textStatus, errorThrown, callback) {
        //Standard error handling here
        //Do caller callback
        if (callback) callback();
    }


}, {});


$.Class('Tacky.Models.BaseModel', {
    setup: function() {
        var self = this;

        var standardServices = ['findOne', 'findAll'];

        $.each(standardServices, function(k, v) {
            if (typeof self[v] == 'string') {
                var url = self[v];
                // var generic = v + 'Generic';
                self[v] = function() {
                    var args = Array.prototype.slice.apply(arguments);
                    args.unshift(url);
                    this.genericRequest.apply(self, args)
                };
            }
        });

    },
    blank: null,
    //Attaches any related models to the calling model, this method will trigger a callback with the updated data 
    //each time each of the related models are fetched, and extra final complete callback that informs the caller that all the data is loaded.
    attachRelated: function(data, callback, complete) {
        var self = this;
        var data = $.isArray(data) ? data : [data];

        var callbacks = 0;
        $.each(this.related, function(key, value) {
            callbacks++;
            self.attachOne(data, key, value, function(data) {
                callbacks--;
                callback(data); //when each related model is loaded, call back
                if (callbacks == 0 && complete) complete(data); //final callback
            });
        });
    },
    //used in combindation with attachRelated
    attachOne: function(data, propertyname, model, success) {
        var self = this;
        var callbacks = 0; //Track how many callbacks we expect to receive
        $.each(data, function(k, v) {
            callbacks++;
            window[model].related(v.Id, self.entityTypeId, function(attachdata) {
                attachdata = attachdata === undefined ? [] : attachdata;
                data[k][propertyname] = attachdata;

                var newdata = data.length > 1 ? data : data[0];
                callbacks--;
                if (callbacks == 0) success(newdata, true); //If no more callbacks, all the related data is done
            });
        });
    },
    genericRequest: function(url, params, callback, complete) {
        var self = this;

        //find any holders in the tempalte url, extract these parameters and construct a new url
        var matches = url.match(/({.+?})/gi);
        if (matches) {
            $.each(matches, function(k, v) {
                var clean = v.substr(1, v.length - 2);
                var regex = new RegExp(v, 'gi')
                $.each(params, function(key, value) {
                    if (key != clean) return;
                    url = url.replace(regex, value);
                    delete params[key]; //Remove the parameter from the collection, it was ment for templating the url
                });
            });
        };

        var ajaxOptions = {};
        //The non-extracted parameters are passed to the ajax request as data
        ajaxOptions.data = params;

        //Set the new url as the valid one
        ajaxOptions.url = url;
        ajaxOptions.success = function(data) {
            self.modelSetup(data); //Make sure the model have empty objects even if they are not loaded yet
            if (self.related) self.attachRelated(data, callback, complete);
            callback(data); //Partial callback
        };

        ajaxOptions.complete = complete;

        Tacky.Service.json(ajaxOptions);
    },
    empty: function() {
        var self = this;
        if (!this.blank) {
            var empty = {}; //Create a empty object
            this.modelSetup(empty); //Attach properties, 
            this.blank = empty; //Store in cache
        }
        return this.blank;
    },
    modelSetup: function(data) {

        var self = this;
        data = $.isArray(data) ? data : [data]; //make array
        this.beforeBind(data);
        $.map(data, function(item) {
            if (self.related) {
                $.each(self.related, function(k, v) {
                    item[k] = item[k] || window[v].empty();
                });
            };
        });
    },
    beforeBind: function(data) {
        //Do conversions etc, in this case from asp.net mvc date strings to date objects
        var tempdata = $.isArray(data) ? data : [data];
        $.each(tempdata, function(i, arrayitem) {
            $.each(arrayitem, function(propertyname, propertyvalue) {
                //Turn asp.net mvc formatted dates to javascript date objects (also using Date.js lib.)
                if (!propertyvalue || !propertyvalue.match) return; //If not string
                if (propertyvalue.match(/\/Date\(.*?\d{13}\)\//)) arrayitem[propertyname] = Util.toDateJS(propertyvalue);
            });
        });
        data = tempdata;
    }
}, {


});


$.Class('Tacky.Exception', {
    init: function() {
        window.onerror = this.onError;
    },
    onError: function(msg, script, line) {
        Tacky.Models.ClientError.create({
            Message: msg,
            Script: script,
            Line: line,
            Origin: document.location.href
        });
    }
}, {});

Tacky.Models.BaseModel('Tacky.Models.ClientError', {
    init: function() {

    },
    createUrl: '/clienterror/create',
    haltErrorHandling: false,
    create: function(data) {
        var self = this;
        if (this.haltErrorHandling) return;

        Tacky.Service.postJSON({
            url: this.createUrl,
            data: data,
            success: function(data) {
                console.log(data);
            },
            error: function() {
                self.haltErrorHandling = true; //If logging fails, we don't want to keep trying to log errors, we would possibly enter a loop
            }
        });
    }
}, {});



$.Class('Tacky.Labels', {
    init: function() {
        this.getAllLabels(Tacky.currentSite.languageid); //Dynamically get language
    },
    currentLabels: undefined,
    loadedLabels: [],
    getAllLabels: function(id) {
        $.ajax({
            url: '/language/details/' + id,
            success: function(data) {
                var lbls = {
                    languageId: id,
                    data: data
                };
                Tacky.Labels.loadedLabels.push(lbls);
                Tacky.Labels.currentLabels = lbls;
            },
            async: false
        });
    },
    label: function(controlid, labelid) {
        return EF(Tacky.Labels.currentLabels.data).SingleOrDefault({
            Label: ''
        }, function(d) {
            return d.LabelKey === labelid && d.ControlKey === controlid;
        }).Label;
    }

}, {});


$.Class('Tacky.Navigation', {}, {
    init: function(options) {
        if (options) {
            this.options = $.extend(this.options, options);
        }
        this.render();
    },
    options: {
        placeholder: undefined,
        page: 1,
        callback: undefined
    },
    render: function() {
        var nav = this;
        var next = $('<a class="next ajaxlink" style="float:right">>></a>');
        var previous = $('<a class="previous ajaxlink" style="float:left;"><<</a>');
        $(this.options.placeholder).append(next);
        if (this.options.page > 1) $(this.options.placeholder).append(previous);

        next.click(function() {
            nav.clickHandler(next);
        });
        previous.click(function() {
            nav.clickHandler(previous);
        });
    },
    clickHandler: function(link) {
        var page = link.hasClass('next') ? this.options.page + 1 : this.options.page - 1;
        this.options.callback(page);
    }
});


$.Class('Tacky.News', {}, {
    init: function(options) {
        if (options) {
            this.options = $.extend(this.options, options);
        }
        if (this.options.placeholder === undefined) {
            console.log('Tacky.News: placeholder is a required option, cancelling rendering');
            return;
        }
        this.getNews();
    },
    options: {
        placeholder: undefined,
        page: 1,
        pagesize: 10
    },
    path: '/news',
    navigationPlaceholder: '.g_news .navigation',
    currentPage: 1,
    render: function(data) {
        var news = this;
        $(this.options.placeholder).html(data);
        $(this.options.placeholder).find('.g_news').append('<div class="navigation"></div><div class="g_cb"></div>');
        var nav = $(this.options.placeholder).find(this.navigationPlaceholder);

        new Tacky.Navigation({
            placeholder: this.navigationPlaceholder,
            page: news.options.page,
            callback: function(page) {
                news.options.page = page;
                news.getNews();
            }
        });
    },
    getNews: function() {
        var self = this;
        var urlfrag = Tacky.currentContentPool === null ? '' : '/' + Tacky.currentContentPool;
        $.get(urlfrag + self.path, {
            page: self.options.page,
            pagesize: self.options.pagesize
        }, function(data) {
            self.currentPage = self.options.page;
            self.render(data);
        });
    }
});


//The adinfo needs to go to the database
$.Class('Tacky.VideoAd', {
    ads: [{
        url: 'http://d29k0cco2img05.cloudfront.net/m/201202/474601_1024.mp4',
        link: null,
        sites: [3]
    }],
    randomAd: function() {
        return EF(this.ads).Shuffle().FirstOrDefault(null, function(d) {
            return EF(d.sites).Contains(Tacky.currentSite.id);
        });
    }
}, {});


$.Class('Tacky.VideoPlayer', {
    options: {
        streamingUrlBase: 'rtmp://s3k8qegf9cfv53.cloudfront.net/cfx/st/_definst_/mp4:',
        streamingUrlRegex: new RegExp('.*?\.net\/'),
        initHeight: 380,
        initWidth: 676,
        ctrlbarHeight: 32,
        url: null,
        thumb: null,
        wmode: 'window',
        skin: '/content/jwplayer/lulu/lulu.zip',
        preroll: undefined,
        postroll: undefined,
        placeholderid: undefined,
        flashDefault: [{
            type: "flash",
            src: "/content/jwplayer/player.swf"
        }, {
            type: "html5",
            config: {
                file: '',
                provider: "video"
            }
        }],
        html5Default: [{
            type: "html5",
            config: {
                file: '',
                provider: "video"
            }
        }, {
            type: "flash",
            src: "/content/jwplayer/player.swf"
        }]
    }
}, {
    uniquenumber: null,
    placeholder: null,
    player: null,
    html5Mode: false,
    playingAd: false,
    options: null,
    playlist: [],
    streamprovider: 'rtmp',
    streamer: 'rtmp://s3k8qegf9cfv53.cloudfront.net/cfx/st',
    init: function(options) {
        var self = this;
        //Set the options as the default options
        var opt = $.extend({}, Tacky.VideoPlayer.options, options);
        this.options = opt;

        //extract url from formats
        opt.url = this.handleFormats();

        var adtitle = 'ad';
        var adprovider = 'video';

        //Generate unique number
        this.uniquenumber = Math.floor(Math.random() * 1000000000);
        this.placeholder = opt.placeholderid

        //Detect if we should use html5 or flash
        if (!jwplayer.utils.hasFlash() || $.browser.mobile) this.html5Mode = true;

        if (this.html5Mode) $('#' + this.placeholder).wrap('<div id="' + this.placeholder + '_wrapper"></div>')

        //Set url to the different options configs
        opt.flashDefault[1].config.file = opt.url;
        opt.html5Default[0].config.file = opt.url;

        var mode = opt.flashDefault;
        this.playlist = [];
        if (window.location.search.match('beta')) {
            mode = opt.html5Default;
            this.playlist = [{
                file: opt.url,
                image: opt.thumb,
                provider: 'video'
            }];

        } else {
            this.playlist = [this.getPlayListItem(opt.url)];
        }

        //Create a playlist containing at least one item, then add post/pre roll after that
        //setup preroll if it is supplided
        if (opt.preroll) {
            this.playlist.unshift({
                file: opt.preroll.url,
                image: opt.thumb,
                title: adtitle,
                provider: adprovider
            });
        }

        //setup postroll if it is supplied
        if (opt.postroll) {
            this.playlist.push({
                file: opt.postroll.url,
                image: opt.thumb,
                title: adtitle,
                provider: adprovider
            });
        }

        //create the player instance
        this.player = jwplayer(this.placeholder);

        //Setup the jwplayer through their javascript code
        this.player.setup({
            playlist: this.playlist,
            modes: mode,
            repeat: 'list',
            name: 'player.swf',
            controlbar: 'bottom',
            height: opt.initHeight + opt.ctrlbarHeight,
            width: opt.initWidth,
            displayclick: 'fullscreen',
            autoplay: true,
            wmode: opt.wmode,
            skin: opt.skin,
            plugins: 'gapro-2',
            events: {
                onPause: function() {
                    self.gotoAd.apply(self, arguments);
                },
                onTime: function() {
                    self.setupAdInfo.apply(self, arguments);
                },
                onMeta: function() {
                    self.resizePlayer.apply(self, arguments);
                },
                onPlaylistItem: function() {
                    self.onplaylistChange.apply(self, arguments);
                }
            }
        });
    },
    resizePlayer: function(event) {
        //Resizes the player in height to accomodate for the potential difference with the current media player size and the video playing in it        
        if (event.metadata.width && event.metadata.height) {
            ev = event;
            var marginOfError = 0.01;
            var width = event.metadata.width;
            var height = event.metadata.height;
            var currentMediaAspect = width / height;

            var currentAspect = this.player.getWidth() / (this.player.getHeight() - this.options.ctrlbarHeight);

            if (currentMediaAspect < currentAspect - marginOfError || currentMediaAspect > currentAspect + marginOfError) {
                var newheight = this.options.initWidth / currentMediaAspect + this.options.ctrlbarHeight;
                this.player.resize(this.options.initWidth, newheight);
                $('#' + this.placeholder + '_wrapper').height(newheight);
            }
        }
    },
    gotoAd: function(event) {
        if (this.options.preroll.link !== null && this.player.getPlaylistItem().index == 0) {
            this.openLink(this.options.preroll.link);
        }
        if (this.options.postroll.link !== null && this.player.getPlaylistItem().index == 2) {
            this.openLink(this.options.post.link);
        }
    },
    openLink: function(link) {
        Tacky.trackOutboundLink('VideoAdClicked', link);
        if (!window.open(link)) $('#' + this.placeholder + '_wrapper').after('<a style="display:block;padding:5px;text-align:center" target="_blank" href="' + link + '">Click here to go to the advertiser link.</a>');
    },
    setupAdInfo: function(event) {
        var adInfoUnique = '#adinfo_' + this.uniquenumber;

        if (this.player.getPlaylistItem().title == 'ad') {
            $(adInfoUnique + ' #adtime').html(Math.floor(this.player.getDuration() - this.player.getPosition()));
            if (!this.playingAd) {
                this.playingAd = true;

                $('#' + this.placeholder + '_wrapper').after('<div id="adinfo_' + this.uniquenumber + '" style="display:none;text-align:center;width:' + this.options.initWidth + 'px"></div>');
                $(adInfoUnique).html(Tacky.Labels.label('videoviewer', 'advertisement').replace('{0}', '<span id="adtime"></span>'))
                $(adInfoUnique).fadeIn('slow');
            }
        } else {
            $(adInfoUnique).fadeOut('fast');
            playingAd = false;
        }
    },
    getPlayListItem: function(url, thumb) {
        if (this.html5Mode) {
            return {
                file: url,
                provider: 'video',
                title: ''
            };
        } else {
            url = url.replace(this.options.streamingUrlRegex, '');
            return {
                file: url,
                provider: this.streamprovider,
                streamer: this.streamer,
                title: ''
            };
        }
    },
    //changes the format of the current video, restarts the video if currently playing or just replaces the playlist if in preroll state
    changeFormat: function(url) {
        var self = this;
        var current = this.player.getPlaylistItem();
        var playlist = this.player.getPlaylist();
        if (current.title != 'ad') {
            //ad is not playing change playlist now, remove first item
            playlist[1] = this.createStreamingPlaylistItem(url);
            this.player.load(playlist);
        } else {
            //Ad is playing, change playlist after ad finishes
            this.onchangeEvents.push(function() {
                playlist[1] = self.createStreamingPlaylistItem(url);
                self.playlist = playlist;
                self.player.load(self.playlist);

            });
        }
    },
    onchangeEvents: [],
    onplaylistChange: function(event) {
        this.onchangeEvents[0]();
        this.onchangeEvents = [];
    },
    //handles the formats and selects the correct format based on user choice, defaults and user device
    handleFormats: function() {
        var self = this;
        var HD = this.options.formats['3072'];
        var SD = this.options.formats['1024'];
        var mobile = this.options.formats['768'];
        var displayurl = HD ? HD : SD;
        if ($.browser.mobile && mobile) displayurl = mobile;



        if (this.options.formats > 1) {
            $.each(this.options.formats, function(bitrate, url) {

                var name = bitrate == 768 ? 'Mobile' : 'Standard';
                var name = bitrate == 3072 ? 'HD' : name;
                var newUrl = self.options.formats[bitrate + ''];
                $('#videoVersions').append('<input type="radio" name="bitrate" id="b-' + bitrate + '" data-url="' + newUrl + '" /><label for="b-' + bitrate + '">' + name + '</label>');
            });

            $('#videoVersions').find('input').each(function() {
                $(this).click(function() {
                    var url = $(this).attr('data-url');
                    self.changeFormat(url);
                    return false;
                });
            });
        }

        $('#videoVersions input').each(function() {
            var $this = $(this);
            if ($this.attr('data-url') == displayurl) $this.attr('checked', true);
        });

        $('#videoVersions').buttonset();

        return displayurl;
    }

});

//Make sure init have been called before anything related to currentSite etc
$(function() {

    //Remove news column specifically for .fi
    if (Tacky.currentSite.id !== 10) {
        new Tacky.News({
            placeholder: '#news'
        });
    }

    //Load external widgets, plugins ++ (facebook, twitter, analytics, etc....)
    Tacky.setupExternal();
});
