$(document).ready(function() {
    // preload the loading and error images
    function preload(image_url) {
        $("<img />").attr("src", image_url);
    }
    preload(LOADING_URL);
    preload(ERROR_URL);
    
    var time = new Date().getTime();

    var hide_notes = true;

    function move(url) {
        $('#play_area,#play_area a').css('cursor','wait');
        // show a loading image
        $('#play_area .actions')
            .find('.status')
                .html('<img title="loading..." src="'+LOADING_URL+'"/> loading...')
            .end()
            .find('input')
                .hide();
    
        // do the ajax call
        $.ajax({
            type: 'GET',
            url: url,
            data: { t: time },
            success: function(data) {
                // remove event handlers for forms and a links
                $('#play_area form, #play_area a').unbind();
                
                // use empty div etc to keep safari 3 happy (and iphone)
                // this is used in load method of jquery
                data=$('<div></div>').append(data.replace(/<script(.|\s)*?\/script>/g, ""));
                var new_html = data.find('#play_area');
                $('#play_area').html(new_html).css('cursor','');
                attachToPlayArea();
                scrollToConfirm();
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                $('#play_area,#play_area a').css('cursor','');
                $('#play_area .actions')
                    .find('input')
                        .show()
                    .end()
                    .find('.status')
                        .html('<img title="error" src="'+ERROR_URL+'"/>');
            }
        });
    }

    function scrollTop() {
        if ( document.documentElement && document.documentElement.scrollTop ) {
            return document.documentElement.scrollTop;
        }
        if ( document.body && document.body.scrollTop ) {
            return document.body.scrollTop;
        }
        return 0;
    }

    function ensureFullyVisible(element) {
        var offset = element.offset();
        var confirmTop    = offset.top;
        var confirmBottom = confirmTop + element.height();
    
        var winTop    = scrollTop();
        var winHeight = $(window).height();
        var winBottom = winTop + winHeight;
    
        var targetOffset = winTop;
        if ( confirmTop < winTop ) {
            targetOffset = confirmTop;
        }
        else if ( confirmBottom > winBottom ) {
            targetOffset = confirmBottom - winHeight;
        }
    
        if ( targetOffset != winTop ) {
            $('html,body').animate({scrollTop: targetOffset}, 250);
        }
    }

    function scrollToConfirm() {
        if ( $('#make_move').size() > 0 ) {
            ensureFullyVisible($('#make_move'));
        }
    }

    function attachMoveEvents(elements, event, attribute) {
        elements.each(function(i) {
                var target = $(this);
                $(this).bind(event, function(event) {
                    event.preventDefault();
                    move(target.attr(attribute));
                });
        });
    }

    function attachToPlayArea() {
        var playArea = $('#play_area');
        attachMoveEvents(playArea.find('a.move_link'), 'click', 'href');
        attachMoveEvents(playArea.find('form.move_link'),'submit', 'action');
        $('#play_area form').submit(function() {
                // on submit we want to disable submit buttons,
                // to avoid double-submitting
                $('#play_area form :submit').attr('disabled', 'disabled');
                return true;
        });
        attachToNotes();
    }

    function loadActiveGames(url, div, callback, errorCallback) {
        // extract the user from the url (of form /user/<username>/active.json)
        var username = /\/user\/([^\/]+)\/.*/.exec(url)[1];
        $.ajax({
                url: url,
            data: { t: time },
            dataType: 'json',
            error: errorCallback,
            success: function(json) {
                if ( json.length == 0 ) {
                    div.hide();
                }
            
                // sort the json by updated date
                json.sort(function(a,b) {
                    return Date.parse(a.updated) - Date.parse(b.updated);
                });
            
                var gameList = $('<ul></ul>');
                var even = true;
                for ( var i = 0; i < json.length; i++ ) {
                    var game=json[i];
                    // examine the fen to see who's turn it is
                    var whichTurn = /.*\s(w|b)\s.*/.exec(game.fen)[1];
                    var userToMove = whichTurn == 'w'? game.white : game.black;
                    var usersTurn = userToMove == username;
                    if ( !usersTurn && !game.allow_undo )
                        continue;
                
                    // if game has finished it's not the user's
                    // turn, but we want to show it in the list
                    if ( game.result ) {
                        usersTurn = false;
                    }
                    
                    var game_title = game.title;
                    if ( game.allow_undo ) {
                        game_title += ' [undo allowed]';
                        usersTurn = true;
                    }
                    
                    gameList.append(
                        $('<li> </li>')
                            .addClass(even? 'even':'odd')
                            .addClass(usersTurn? 'users_turn':'')
                            .append(
                                $('<a href="/game/'+game.id+'"></a>')
                                .text(game_title)
                            )
                    );
                
                    even = !even;
                }
                div.html(gameList);
            
                callback();
            }
        });
    }

    function attachGamesDropDown() {
        $('#user_actions .games a').each(function() {
                var gamesLink = $(this);
            var activeCount = gamesLink.find('.active_count');
            if ( activeCount.size() == 0 )
                return;
        
            activeCount.attr('title', 'click to show active games');
            activeCount.hover(
                function() {
                    activeCount.addClass('hover');
                },
                function() {
                    activeCount.removeClass('hover');
                }
            );
        
            var dropDown = $('<div class="dropdown" style="display: none;"></div>');
        
            var positionDropDown = function() {
                dropDown.css('top', activeCount.offset().top + activeCount.height());
                // call this twice to ensure we get the correct width
                // as div may have been too close to the edge before
                for ( var i = 0; i < 2; i++ ) {
                    dropDown.css('left', activeCount.offset().left + activeCount.width() - dropDown.width() -1);
                }
            };
        
            dropDown.resize(positionDropDown);
        
            $('#user_actions').after(dropDown);
        
            var url = gamesLink.attr('href')+'/active.json'
        
            var loaded = false;
        
            var errorCallback = function() {
                loaded = false;
                dropDown.html('<img class="status" src="'+ERROR_URL+'" /> error loading ');
                positionDropDown();
            };
        
            activeCount.click(
                function() {
                    dropDown.show();
                    activeCount.addClass('dropDownActive');
                    if ( !loaded ) {
                        dropDown.html('<img class="status" src="'+LOADING_URL+'" /> loading...');
                        loaded =  true;
                        loadActiveGames(url, dropDown, positionDropDown, errorCallback);
                    }
                    positionDropDown();
                    return false;
                }
            );
        
            // click anywhere else will hide the drop down
            $(document).click( function() {
                dropDown.hide();
                activeCount.removeClass('dropDownActive');
            } );
        });
    }

    function attachToNotes() {
        var notes = $('#game_notes');
        if ( notes.size() > 0 ) {
            var show_notes = $('<a id="show_notes" title="leave yourself some notes on this game" href="#">notes</a>');
            $('.formats a:last').after(show_notes);
        
            if ( hide_notes ) {
                hide_notes=false;
                notes.hide();
                notes.find('form').submit(function(event) {
                    event.preventDefault();
                    
                    // disable submit button
                    var status=$(this).find('.status');
                    var submit=$(this).find(':submit')
                
                    submit.attr('disabled','disabled');
                    status.html('<img title="saving..." src="'+LOADING_URL+'"/> saving...');
                
                    var url = $(this).attr('action');
                    $.ajax({
                        type: "POST",
                        url: url,
                        data: { note_text: $(this).find(':input[name=note_text]').val() },
                        success: function() {
                            notes.slideUp('fast',
                                function() {
                                    // re-enable submit button
                                    // and show notes link
                                    submit.removeAttr('disabled');
                                    status.html('');
                                    $('#show_notes').show();
                                }
                            );
                        },
                        error: function () {
                            submit.removeAttr('disabled');
                            status.html('<img title="error" src="'+ERROR_URL+'"/>');
                        }
                    });
                });
            }
        
            show_notes.click(function(event) {
                event.preventDefault();
                $('#show_notes').hide();
                notes.slideDown('fast',function() {
                    ensureFullyVisible(notes);
                });
            });
            if ( notes.css('display') != 'none' ) {
                $('#show_notes').hide();
            }
        }
    }

    function scrollToConfirm() {
        if ( $('#confirm').size() > 0 ) {
            ensureFullyVisible($('#confirm'));
        }
    }
    
    $('.show_comment_form').click(function(event) {
        $(this).fadeOut();
        var url = $(this).attr('href');
        var matched = url.match(/#move(\d+)$/);
        if ( matched ) {
            event.preventDefault();
            var move_num = matched[1];
            ensureFullyVisible($('.comment_form_' + move_num).fadeIn());
            $('.comment_form_' + move_num).find(':text').focus();
        }
    });
    
    $.ajaxSetup({ timeout: 40000 });
    
    attachToPlayArea();
    attachGamesDropDown();
});