(function($){

    var PlayerController = function(element) {
        this.element = element;

        var isIOS = VideoJS.isIOS();

        var _playerFrame = $(".player-frame", element);
        var _playerBox = $(".player", element);
        var _logo = $(".logo img", element);

//        var options = {
//            playDelayTime: isIOS ? 0 : 1000,
//            shutterDelayTime: isIOS ? 0 : 1000,
//            shutterOpenTime: isIOS ? 0 : 2000,
//            shutterCloseTime: isIOS ? 0 : 1000,
//            logoAnimationTime: 1000
//        };

        var options = {
            playDelayTime: 2000,
            shutterDelayTime: 0,
            shutterOpenTime: 0,
            shutterCloseTime: 0,
            logoAnimationTime: 1000
        };

        var createPlayer = function(id) {
            _playerBox.empty();
            var player = $("#player-tmpl").tmpl({id: id}).appendTo(_playerBox);

            //_playerBox.append(player);

            var onEnded = function() {
                videoPlayer.hideBigPlayButtons();
                
                if (videoPlayer.video.webkitExitFullscreen) {
                    videoPlayer.video.webkitExitFullscreen();
                }

                _hidePlayer();
            };

            if (VideoJS.getFlashVersion()) {
                flowplayer("player", {
                    src: "http://static.milbou.be/flowplayer/flowplayer.commercial-3.2.5.swf",
                    wmode: 'opaque'
                }, {
                    key: "#$864c4271e6552e561f1",
                    canvas: {
                        background: "#000"
                    },
                    clip:  {
                        autoPlay: true,
                        autoBuffering: true,
                        onFinish: function() {
                            this.getPlugin("play").css({opacity: 0}); // Hide the "play again' button on end.
                            onEnded();
                        }
                    }
                });
            } else {
                $('.vjs-flash-fallback', player).hide();
            }
            
            // Setup the newly created video player.
            var videoPlayer = VideoJS.setup($("video", player).get(0), {
                defaultVolume: 1
            });

            if (videoPlayer.length) {
                videoPlayer = videoPlayer[0]; // Solving some IE weirdness.
            }

            if (videoPlayer.onEnded) {
                videoPlayer.onEnded(onEnded);
            }

            // Either we can play, or we can't.
            if (videoPlayer.html5Supported() || videoPlayer.flashSupported()) {
                // Hide the 'can't play video' stuff.
                $('.vjs-no-video', player).hide();

                // Hide the big play button.
                videoPlayer.hideBigPlayButtons();

                // There is no point in trying to autoplay an iOS device.
                if (!VideoJS.isIOS()) {
                    window.setTimeout(function() { videoPlayer.play(); }, options.playDelayTime);
                }
            } else {
                // We can't show video, so get that out of the way.
                $('video', player).hide();
            }
        };

        var _showPlayer = function(onCompletion) {
            if (_playerFrame.css('display') == 'none') {
                _logo.animate({
                    top: 350,
                    left: 10,
                    width: 250,
                    height: 120
                }, options.logoAnimationTime, function() {
                    _playerFrame.show();
                    onCompletion && onCompletion();
                });
            } else {
                onCompletion && onCompletion();
            }
        };

        var _hidePlayer = function(onCompletion) {
            if (_playerFrame.css('display') != 'none') {
                _playerFrame.hide();
                _logo.animate({
                    top: 100,
                    left: 200,
                    width: 500,
                    height: 240
                }, options.logoAnimationTime, onCompletion);
            } else {
                onCompletion && onCompletion();
            }
        };

        // Stupid hack for Flash fallback.
        window.hidePlayer = function() { _hidePlayer(); };

        this.load = function(id) {
            _showPlayer( function() {
                createPlayer(id);
            });
        };
    };

    var MenuController = function(element, actions) {
        this.element = element;

        //var menuSection = $("#menusection", element);
        var _window = $("#window", element);
        var _details = $("#details", element);
        var _nextButton = $("#menu-next", element);
        var _prevButton = $("#menu-previous", element);

        var _updateButtons = function() {
            var current = _details.data("current") || 0;
            var next = current + 1;
            var previous = current - 1;
            var min = -(_details.width() - _window.width());
            var max = 0;

            var nextEnabled = min <= -(next * 160);
            var prevEnabled = -(previous *160) <= max;

            _nextButton[nextEnabled ? 'addClass' : 'removeClass']('enabled');
            _prevButton[prevEnabled ? 'addClass' : 'removeClass']('enabled');
        };

        var _move = function(to) {
            _details.stop(true, false);
            _details.animate({left: to}, 500, 'easeOutQuad');
            _updateButtons();
        };

        var _moveNext = function() {
            var current = _details.data("current") || 0;
            var next = current + 1;
            var left = -(next * 160);
            var min = -(_details.width() - _window.width());

            if (min <= left) {
                _details.data("current", next);
                _move(left);
            }
        };

        var _movePrevious = function() {
            var current = _details.data("current") || 0;
            var next = current - 1;
            var left = -(next * 160);
            var max = 0;

            if (left <= max) {
                _details.data("current", next);
                _move(left);
            }
        };

        _nextButton.click(function() {
            _moveNext();
            return false;
        });

        _prevButton.click(function() {
            _movePrevious();
            return false;
        });

        var _createDetails = function(id, sprite, items) {
            var width = 40 + Math.ceil(items.length / 4) * 160;

            _details.css('width', width);

            $.each(items, function(index, value) {
                var left = Math.floor(index / 4) * 160 + 40;
                var top = index % 4 * 50;
                var item = $('#detail-tmpl')
                    .tmpl()
                    .css(
                    {
                        left: left,
                        top: top
                    })
                    .click(function() { $.address.value(id + '/' + value); })
                    .hover(
                        function() { $('.button', this).stop(true, false).css('background-color', '#000'); },
                        function() { $('.button', this).stop(true, true).animate({ 'background-color': '#f00'}, 500); }
                    )
                    .find('.preview').css({
                        background: 'url(http://media.milbou.be/s/' + sprite + ') no-repeat 0 ' + (index * -40) + 'px'
                    })
                    .end().appendTo(_details);
            });

            $('<div>&nbsp;</div>').addClass('marker').css({left: 5, top: (id - 1) * 50}).appendTo(_details);

        };

        var _hideMenu = function(onCompletion) {
            _details.animate({ left: -_details.width() }, 500, 'easeInQuad', onCompletion);
        };

        var _showMenu = function(onCompletion) {
            _details.animate({left: 0}, 500, 'easeOutQuad', onCompletion);
        };

        var _loadMenu = function(id, onCompletion) {
            if (actions.getMenu) {
                actions.getMenu(id, function(data) {
                    _details.empty();
                    _details.data('current', 0);
                    _details.data('menu', id);
                    _details.css({left: _window.width()});
                    _createDetails(id, data.sprite, data.items);
                    _updateButtons();

                    onCompletion && onCompletion();
                });
            }

        };

        var _sendMail = function(info) {
            var contact = $('div.contact', info);

            var mail = {
                Name: $('input[name=name]', contact).val(),
                Email: $('input[name=email]', contact).val(),
                Message: $('textarea[name=message]', contact).val()
            };

            $("input[type=button]", info).remove();
            var result = $("<p></p>").addClass('result').appendTo(contact);

            actions.sendMail(
                mail,
                function() {
                    result.html("Thanks!");
                },
                function() {
                    result.html("An error has occurred and has been logged.");
                }
            );
        };

        var _createInfo = function() {
            _details.css({width: _window.width()});

            var info = $('#info-tmpl').tmpl().appendTo(_details);

            info.find('.scrollbox').jScrollPane();

            $('ul.languages > li', info).click(function() {
                var selected = this;
                var page = $(this).attr('data-page');
                $('ul.languages > li', info).each(function() {
                    var li = $(this);
                    if (this == selected) {
                        li.addClass('selected');
                    } else {
                        li.removeClass('selected');
                    }
                });
                $('div.scrollbox, div.contact', info).each(function() {
                    var div = $(this);
                    if (div.hasClass(page)) {
                        div.show();
                        if (div.hasClass('scrollbox')) {
                            div.jScrollPane();
                        }
                    } else {
                        div.hide();
                    }
                });
            });

            $('input[type=button]', info).click(function() {
                _sendMail(info);
            });

            // Do other stuff, like hook-up events, here.
        };

        var _loadInfo = function(onCompletion) {
            _details.empty();
            _details.data('current', 0);
            _details.data('menu', 'info');
            _details.css({left: _window.width()});
            _createInfo();
            _updateButtons();

            onCompletion && onCompletion();
        };

        this.load = function(id) {

            var currentMenu = _details.data('menu') || 0;

            if (currentMenu != id) {
                if (id == 'info') {
                    _hideMenu(function() { _loadInfo(_showMenu);});
                } else if (!isNaN(id)) {
                    _hideMenu(function() { _loadMenu(id, _showMenu); });
                }
            }
        };

        this.getCurrentMenu = function() {
            return _details.data('menu') || 0;
        };

        _updateButtons();
    };

    var FrontController = function(element, actions) {
        this.element = element;
        this.player = $("#player", element);
        this.menuController = new MenuController(element, actions);
        this.playerController = new PlayerController($(".playersection", element))
    };

    $.fn.front = function(actions) {
        return this.front = new FrontController(this, actions);
    };

    $.fn.email = function() {
        $("a.email", this).each(function () {
            var element = $(this);
            var email = element.html().replace("_", "@");
            element.attr("href", "mailto:" + email);
            element.html(email);
        })
    };

})(jQuery);

var actions;
var menus;
var imageCache = [];

jQuery(function() {
    $(".footer").email();
    $(".button").each(function() { this.unselectable = "on" });

    $("a").live('dragstart', function(event) { event.preventDefault(); }); // Fix for the way Flowplayer loads and allows dragging the video while it's playing (i.e. can't change the volume).

    var frontController = $("#front").front({
        getMenu: function(id, success) {

            if (menus && menus.length) {
                for (var index = 0; index < menus.length; ++index) {
                    if (menus[index].id == id) {
                        return success(menus[index]);
                    }
                }
            }

            // fallback.
            $.getJSON(actions.getMenu + '/' + id, success);
        },
        sendMail: function(mail, success, error) {
            $.ajax({
                url: actions.sendMail,
                type: 'POST',
                data: JSON.stringify(mail),
                contentType: 'application/json; charset=utf-8',
                success: success,
                error: error
            });
        }
    });

    $.address.history(false).change(function(event) {

        /*
            The address takes one of the following values:

            '/menuId' (e.g. '/1'):
                This means that the specified menu needs to be loaded in the background. The current video does not need
                to be replaced.

            '/menuId/videoId' (e.g. '/1/2'):
                This means that the specified menu needs to be loaded, should it not be the currently displayed menu.
                Also, the specified video needs to be loaded and playing should start immediately, even if it's the
                same video already playing.
         */

        var menuId = event.pathNames[0];
        var videoId = event.pathNames[1];

        if (!menuId && !videoId) {
            // Sent to home, we move to the first menu.
            $.address.value('/1');
        } else {
            if (menuId) {
                frontController.menuController.load(menuId);
            }

            if (videoId) {
                frontController.playerController.load(videoId);
            }
        }
    });

    $('.button[data-menu]').click(function() {
        var value = $(this).attr('data-menu');

        if (value == 'demoreel') {
            // Demoreel is special.
            value = '/' + frontController.menuController.getCurrentMenu() + '/53'; // This is the media id for the demoreel.
        }

        $.address.value(value);
    });

    // Let's preload the sprites
    if (menus && menus.length) {
        for (var index = 0; index < menus.length; ++index) {
            var img = document.createElement('img');
            img.src = 'http://media.milbou.be/s/' + menus[index].sprite;
            imageCache.push(img);
        }
    }
});
