$(function(){
    var $puzzleInfos = $('#puzzle-play-infos');
    var $puzzleUI = $('#puzzle-play');
    var $startButton = $('#puzzle-play-start button');
    var $startDiv = $('#puzzle-play-start');
    var $rankingModal = $('#puzzle-ranking');
    var $commentsComponent = $('#puzzle-comments');
    var $imageEnd = $('#puzzle-play-image');
    var $end = $('#puzzle-play-end');
    var $backButton = $('#puzzle-play-back, #puzzle-play-end button.close');
    var $ratesComponent = $('#puzzle-play-end-rate');
    var $rates = $('*[data-rate]', $ratesComponent);

    var fadeInSpeed = 600;

    var deleteSave = false;

    // Save the settings.
    function savePuzzleSettings(settings, callback) {
        $.ajax({
            url: $('#puzzle-settings').attr('action'),
            type: 'put',
            data: JSON.stringify({
                'bordered_cells': settings.borderedCells,
                'fixed_preview': settings.fixedPreview,
                'preview_size': settings.previewScale,
                'colored_hints': settings.coloredHints,
                'background_contrast': settings.backgroundContrast,
                'background_color': settings.backgroundColor,
                'draggable_grid': settings.draggableGrid,
                'highlight_row_and_col': settings.highlightRowAndCol,
            }),
            complete: function() {
                if (!_.isUndefined(callback)) {
                    callback();
                }
            }
        });
    }

    // Start a new game.
    function startGame(callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-start'),
            type: 'post',
            data: JSON.stringify({
                'delete_save': deleteSave,
            }),
            success: function(data) {
                $puzzleUI.attr('data-game-started', true);
                $puzzleUI.attr('data-game-id', data.game.id);
                $puzzleUI.attr('data-game-created', data.game.created_at);
                $puzzleUI.attr('data-game-time', Date.now());
                $puzzleUI.attr('data-game-saves', data.saves);
                $puzzleUI.attr('data-game-help-revealroworcolumn-count', data.helps.reveal_row_or_column);
                $puzzleUI.attr('data-game-help-revealsquare-count', data.helps.reveal_square);
                $puzzleUI.attr('data-game-help-fixsquares-count', data.helps.fix_squares);
                $puzzleUI.attr('data-game-help-revealroworcolumn-description', data.descriptions.reveal_row_or_column);
                $puzzleUI.attr('data-game-help-revealsquare-description', data.descriptions.reveal_square);
                $puzzleUI.attr('data-game-help-fixsquares-description', data.descriptions.fix_squares);
                $puzzleUI.attr('data-game-help-save-description', data.descriptions.save);
                $puzzleUI.attr('data-game-help-reset-description', data.descriptions.reset);
                $puzzleUI.attr('data-game-help-fixsquares-noerror', data.descriptions.fix_squares_no_error);

                if (!_.isUndefined(data.save)) {
                    $puzzleUI.attr('data-solution', data.save.solution);
                    $puzzleUI.attr('data-prevtime', data.save.time);
                } else {
                    $puzzleUI.attr('data-solution', '');
                    $puzzleUI.attr('data-prevtime', '0');
                }

                $('.start', $startButton).hide();
                $('.resume', $startButton).show();
                $('.alert', $startDiv).hide();
                $('.pause', $startDiv).show();

                if (!_.isUndefined(callback)) {
                    callback();
                }
            },
            complete: function() {
                deleteSave = false;
            }
        });
    }

    // Reset the game.
    function resetGame() {
        destroyPuzzleUI();
        deleteSave = true;
        $puzzleUI.attr('data-game-started', false);
        $startButton.trigger('click');
    }

    // Check the solution of the puzzle.
    function checkGame(solution, pause, callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-check').replace(':gameid', $puzzleUI.attr('data-game-id')),
            type: 'put',
            data: JSON.stringify({'solution': solution, 'pause': parseInt(pause, 10)}),
            success: function(data) {
                $end.hide();

                $imageEnd.attr('src', data.image.full.size1x).attr('srcset', data.image.full.size1x+', '+data.image.full.size2x+' 2x').hide();

                $('#puzzle-play-end-title').text(data.status).show().css('opacity', '0.0');
                $('#puzzle-play-end-time').text(data.time.description).show().css('opacity', '0.0');
                $('#puzzle-play-end-description').text(data.description).show().css('opacity', '0.0');
                $('#puzzle-play-end-image').attr('src', data.image.small.size1x).attr('srcset', data.image.small.size1x+', '+data.image.small.size2x+' 2x').show().css('opacity', '0.0');
                $('#puzzle-play-end-rate').show().css('opacity', '0.0');
                $backButton.show().css('opacity', '0.0');

                if (!_.isUndefined(data.score)) {
                    $('#puzzle-play-end-score').text( data.score.description).show().css('opacity', '0.0');
                } else {
                    $('#puzzle-play-end-score').text('').hide();
                }

                if (!_.isUndefined(data.from) && !_.isUndefined(data.to)) {
                    var percent = (data.from.points-data.from.step_lower_boundary)/(data.from.step_upper_boundary-data.from.step_lower_boundary)*100;
                    $('#puzzle-play-end-level-and-step').show().css('opacity', '0.0');
                    $('#puzzle-play-end-level').text(data.from.level_name);
                    $('#puzzle-play-end-step').text(data.from.step);
                    $('#puzzle-play-end-progress').show().css('opacity', '0.0');
                    $('#puzzle-play-end-progress .progress-bar').attr('aria-valuenow', data.from.points).attr('aria-valuemin', data.from.step_lower_boundary).attr('aria-valuemax', data.from.step_upper_boundary).css('width', percent+'%');
                } else {
                    $('#puzzle-play-end-level-and-step').hide().attr('data-animate-trigger', '');
                    $('#puzzle-play-end-progress').hide();
                    $('#puzzle-play-end-bonus').hide();
                }

                if (!_.isUndefined(data.bonuses)) {
                    var $container = $('#puzzle-play-end-bonus');
                    for (var key in data.bonuses) {
                        $container.append($('<div>'+data.bonuses[key].description+'</div>'));
                    }
                    $container.show().css('opacity', '0.0');
                } else {
                    $('#puzzle-play-end-bonus').hide();
                }

                var rate = data.rate
                if (!_.isUndefined(rate)) {
                    $rates.removeClass('selected');
                    $('*[data-rate='+rate+']', $ratesComponent).addClass('selected');
                }

                endGame(fadeInSpeed);
                
                $('h1').fadeOut(fadeInSpeed);
                $puzzleInfos.fadeOut(fadeInSpeed, function() {
                    hideGameUI();
                    destroyPuzzleUI();

                    $startDiv.hide();
                    $end.show();
                    $('#puzzle-play-end-title').stopAnimate().startAnimate();

                    if (!_.isUndefined(data.from) && !_.isUndefined(data.to)) {
                        setTimeout(function(){
                            var updateProgress = function(){
                                var percent = (data.to.points-data.to.step_lower_boundary)/(data.to.step_upper_boundary-data.to.step_lower_boundary)*100;
                                $('#puzzle-play-end-progress .progress-bar').attr('aria-valuenow', data.to.points).attr('aria-valuemin', data.to.step_lower_boundary).attr('aria-valuemax', data.to.step_upper_boundary).css('width', percent+'%');
                                $('#puzzle-play-end-level').text(data.to.level_name);
                                $('#puzzle-play-end-step').text(data.to.step);
                            }
    
                            $('#puzzle-play-end-score').stopAnimate().attr('data-effect', 'fadeOutDown').attr('data-animate-hide', 'true').startAnimate();
    
                            if (data.from.level == data.to.level && data.from.step == data.to.step) {
                                updateProgress();
                            } else {
                                $('#puzzle-play-end-progress .progress-bar').css('width', '100%');
                                setTimeout(function(){
                                    updateProgress();

                                    $('#puzzle-play-end-level-and-step, #puzzle-play-end-progress, #puzzle-play-end-score').stopAnimate().removeAttr('data-animate-trigger').attr('data-animate', false);

                                    if (data.from.level != data.to.level) {
                                        $('#puzzle-play-end-level').startAnimate();
                                    }
                                    if (data.from.step != data.to.step) {
                                        $('#puzzle-play-end-step').startAnimate();
                                    }
                                    $('#puzzle-play-end-bonus').startAnimate();
                                }, 1250);
                            }
                        }, 9000);
                    }
                });
            },
            complete: function(){
                if (!_.isUndefined(callback)) {
                    callback();
                }
            },
        });
    }

    // Save the current game.
    function saveGame(solution, time, pause, callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-save'),
            type: 'post',
            data: JSON.stringify({'solution': solution, 'pause': parseInt(pause, 10)}),
            success: function(data) {
                window.updateSavesCounter(data.remaining_saves);
                notifyOk(data.status, '');
            },
            complete: function(){
                if (!_.isUndefined(callback)) {
                    callback();
                }
            },
        });
    }

    // Use a help : fix the squares.
    function useHelpFixSquares(solution, callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-help-fixsquares').replace(':gameid', $puzzleUI.attr('data-game-id')),
            type: 'put',
            data: JSON.stringify({'solution': solution}),
            success: function(data) {
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(data.squares, data.count);
            },
            error: function(){
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(undefined, -1);
            },
        });
    }

    // Use a help : reveal a square.
    function useHelpRevealSquare(column, row, callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-help-revealsquare').replace(':gameid', $puzzleUI.attr('data-game-id')),
            type: 'put',
            data: JSON.stringify({'x': column.toString(), 'y': row.toString()}),
            success: function(data) {
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(data.squares, data.count);
            },
            error: function(){
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(undefined, -1);
            },
        });
    }

    // Use a help : reveal a row or a column.
    function useHelpRevealRowOrColumn(isRow, index, callback) {
        $.ajax({
            url: $puzzleUI.attr('data-url-help-revealroworcol').replace(':gameid', $puzzleUI.attr('data-game-id')),
            type: 'put',
            data: JSON.stringify({'type': (isRow ? "row" : "col"), 'index': index.toString()}),
            success: function(data) {
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(data.squares, data.count);
            },
            error: function(){
                if (_.isUndefined(callback)) {
                    return;
                }

                callback(undefined, -1);
            },
        });
    }

    // Show the puzzle and hide the infos.
    $startButton.on('click', function() {
        //$startDiv.fadeOut(function() {
            if ($puzzleUI.attr('data-game-started') == 'true') {
                showGameUI();
                return;
            }

            startGame(function(){
                $puzzleUI.show();
                
                initializePuzzleUI({
                    createMode: false,
                    testMode: false,
                    rows: {
                        count: parseInt($puzzleUI.attr('data-rows-count'),10),
                        hints: $puzzleUI.attr('data-rows-hints')
                    },
                    cols: {
                        count: parseInt($puzzleUI.attr('data-cols-count'),10),
                        hints: $puzzleUI.attr('data-cols-hints')
                    },
                    solution: $puzzleUI.attr('data-solution'),
                    time: $puzzleUI.attr('data-game-time'),
                    prevtime: parseInt($puzzleUI.attr('data-prevtime'),10),
                    saves: parseInt($puzzleUI.attr('data-game-saves'),10),
                    help: {
                        revealRowOrColumn: {
                            count: parseInt($puzzleUI.attr('data-game-help-revealroworcolumn-count'),10),
                            description: $puzzleUI.attr('data-game-help-revealroworcolumn-description'),
                        },
                        revealSquare: {
                            count: parseInt($puzzleUI.attr('data-game-help-revealsquare-count'),10),
                            description: $puzzleUI.attr('data-game-help-revealsquare-description'),
                        },
                        fixSquares: {
                            count: parseInt($puzzleUI.attr('data-game-help-fixsquares-count'),10),
                            description: $puzzleUI.attr('data-game-help-fixsquares-description'),
                            noerror: $puzzleUI.attr('data-game-help-fixsquares-noerror'),
                        },
                        save: {
                            description: $puzzleUI.attr('data-game-help-save-description'),
                        },
                        reset: {
                            description: $puzzleUI.attr('data-game-help-reset-description'),
                        },
                        buttons: {
                            validate: $puzzleUI.attr('data-game-help-button-validate-text'),
                            cancel: $puzzleUI.attr('data-game-help-button-cancel-text'),
                        },
                    },
                    text: {
                        loading: $puzzleUI.attr('data-game-text-loading'),
                        back: $puzzleUI.attr('data-game-text-back'),
                        check: $puzzleUI.attr('data-game-text-check'),
                        save: $puzzleUI.attr('data-game-text-save'),
                        tempValidate: $puzzleUI.attr('data-game-text-temp-validate'),
                        tempDelete: $puzzleUI.attr('data-game-text-temp-delete'),
                        helpRevealSquare: $puzzleUI.attr('data-game-text-help-revealsquare'),
                        helpRevealRowOrCol: $puzzleUI.attr('data-game-text-help-revealroworcol'),
                        helpFixSquares: $puzzleUI.attr('data-game-text-help-fixsquares'),
                        historyBack: $puzzleUI.attr('data-game-text-history-back'),
                        historyForward: $puzzleUI.attr('data-game-text-history-forward'),
                        reset: $puzzleUI.attr('data-game-text-reset'),
                    },
                    saveSettings: savePuzzleSettings,
                    resetGame: resetGame,
                    saveGame: saveGame,
                    checkGame: checkGame,
                    useHelpFixSquares: useHelpFixSquares,
                    useHelpRevealSquare: useHelpRevealSquare,
                    useHelpRevealRowOrColumn: useHelpRevealRowOrColumn,
                }, 'puzzle-play');
            });
        //});
    });

    // Hide the end part and show the infos.
    $backButton.on('click', function() {
        $backButton.attr('disabled','disabled');
        $end.fadeOut(fadeInSpeed, function(){
            $('h1').fadeIn(fadeInSpeed);
            $puzzleInfos.fadeIn(fadeInSpeed);
            $imageEnd.fadeIn(fadeInSpeed);
            //$commentsComponent.fadeIn(fadeInSpeed);
        });
    })

    // Rate the puzzle.
    $rates.on('click', function(e){
        e.preventDefault();

        var $this = $(this);

        $rates.removeClass('selected');
        $this.addClass('selected');

        $.ajax({
            url: $this.attr('data-rate-url'),
            type: 'put',
            data: JSON.stringify({
                'rate': $this.attr('data-rate'),
            }),
            success: function(data) {
                notifyOk(data.status, '');
            },
        });
    });

    // Load the ranking on show.
    $rankingModal.on('shown.bs.modal', function() {
        $('.ranking', $rankingModal).reloadData();
    });

    // Unload the ranking on hide.
    $rankingModal.on('hidden.bs.modal', function() {
        $('.ranking', $rankingModal).text('');
    });

    window.clearCommentForm = function(){
        $('textarea', $commentsComponent).val('');
    }
})