$(function() { sio = (function() {

    var sio = {};

    var counter = $('#counter');

    var canvasPdf = $('#canvas-pdf').get(0);
    var contextPdf = canvasPdf.getContext('2d');

    var canvasPaint = $('#canvas-paint').get(0);
    var contextPaint = canvasPaint.getContext('2d');

    var pdf;
    var currentPage = 1;

    var startTime = 0;
    var startSlide = 0;
    var refreshIntervalId = 0;

    var pointer = false;
    var shouldUpdatePointer = false;

    var canvasPdfBounding;

    var lasers = {};
    var drawAudienceLasers = false;

    PDFJS.getDocument('/static/uploaded/' + filename + '.pdf').then(function getPdf(_pdf) {
        pdf = _pdf;
        updateUI();
    });

    var socket = io();

    socket.on('welcome', function() {
        socket.emit('speaker', filename, socket.id);
    });

    socket.on('pointer', canvasPointer);

    function filterInt(value) {
        if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))
            return Number(value);
        return NaN;
    }

    var updateUI = function() {

        counter.val(currentPage + '/' + pdf.pdfInfo.numPages);

        $('#previous,#first').prop('disabled', currentPage === 1);
        $('#next,#last').prop('disabled', currentPage === pdf.pdfInfo.numPages);

        pdf.getPage(currentPage).then(function(page) {

            previousPage = currentPage;

            var viewport = page.getViewport(2.0);

            canvasPdf.width = viewport.width;
            canvasPdf.height = viewport.height;

            canvasPaint.width = viewport.width;
            canvasPaint.height = viewport.height;

            $('#canvases').width(canvasPdf.width + 'px');
            $('#canvases').height(canvasPdf.height + 'px');

            canvasPdfBounding = canvasPdf.getBoundingClientRect();

            var renderContext = {
                canvasContext: contextPdf,
                viewport: viewport
            };

            page.render(renderContext);

        });

    };

    function updateAudience() { socket.emit('change-slide', filename, currentPage); }

    function formatTime(ms) {
        var sec = padToTwo(Math.floor((ms / 1000) % 60));
        var min = padToTwo(Math.floor(((ms / 1000 - sec) % 3600) / 60));

        return min + ':' + sec;
    }

    function updateTimers() {
        if (refreshIntervalId !== 0) {
            $('#totalTime').html(formatTime(Date.now() - startTime));
            $('#slideTime').html(formatTime(Date.now() - startSlide));
        }
    }

    function padToTwo(number) {
        if (number<=99) { number = ("0"+number).slice(-2); }
        return number;
    }

    function resetTimeSlide() {
        startSlide = Date.now();
        updateTimers();
    }


    // Check if number is valid, and updates
    // number undefined means sync all clients
    function changeSlide(number) {

        if (isNaN(number) || number < 1 || number > pdf.pdfInfo.numPages) {
            return false;
        }

        if (currentPage === undefined || currentPage === number) {
            updateAudience();
            return true;
        }

        currentPage = number;

        updateUI();
        updateAudience();
        resetTimeSlide();

        return true;

    }

    function canvasPointer(id,x,y) {

        // Clear canvas
        canvasPaint.width = canvasPaint.width;

        if (id != undefined) {
            if (x != undefined && y != undefined) {
                lasers[id] = {x:x, y:y};
            } else {
                delete lasers[id];
            }
        }

        for (var laserIndex in lasers) {

            var laser = lasers[laserIndex];

            if (drawAudienceLasers === true || laserIndex === socket.id) {

                contextPaint.fillStyle = laserIndex === socket.id ? 'red' : 'green';
                contextPaint.beginPath();
                contextPaint.arc(laser.x * canvasPdf.width, laser.y * canvasPdf.height, 10, 0, Math.PI*2, true);
                contextPaint.closePath();
                contextPaint.fill();

            }

        }

    }

    sio.onMouseDown = function(event) {

        var x = event.offsetX / canvasPdf.width;
        var y = event.offsetY / canvasPdf.height;

        socket.emit('pointer', filename, socket.id, x, y);

        pointer = true;
        shouldUpdatePointer = true;

        canvasPointer(socket.id, x, y);

    };

    sio.onMouseMove = function(event) {

        if (pointer) {

            var x = event.offsetX / canvasPdf.width;
            var y = event.offsetY / canvasPdf.height;

            if (shouldUpdatePointer) {
                // Update
                socket.emit('pointer', filename, socket.id, x, y);

                shouldUpdatePointer = false;

                setTimeout(function() {

                    shouldUpdatePointer = true;

                }, 20);

            }

            canvasPointer(socket.id, x, y);

        }

    };

    sio.onMouseUp = function(event) {

        socket.emit('pointer', filename, socket.id);

        pointer = false;
        shouldUpdatePointer = false;

        canvasPointer(socket.id);

    };

    sio.startPresentation = function() {

        startTime = startSlide = Date.now();

        refreshIntervalId = setInterval(updateTimers, 1000);
        updateTimers();

        $('#start').prop('disabled', true);
        $('#stop').prop('disabled', false);

    };

    sio.stopPresentation = function() {

        clearInterval(refreshIntervalId);
        refreshIntervalId = 0;

        $('#start').prop('disabled', false);
        $('#stop').prop('disabled', true);

    };

    sio.changeSlideFromCounter = function() {

        var slideNumber = filterInt($('#counter').val());

        changeSlide(slideNumber);

        // lose focus
        $(':focus').blur();

    };

    sio.switchAudienceLaser = function() {

        var laser = $('#viewer-laser');

        if (drawAudienceLasers === false) {

            // Laser is disabled, will be enabled
            laser.text('Audience laser is enabled');
            laser.removeClass('btn-default').addClass('btn-primary');
            drawAudienceLasers = true;


        } else {

            laser.text('Audience laser is disabled');
            laser.removeClass('btn-primary').addClass('btn-default');
            drawAudienceLasers = false;

        }

        socket.emit('viewer-laser', filename, drawAudienceLasers);

    };

    sio.clearCounter   = function() { $('#counter').val('');             };
    sio.nextSlide      = function() { changeSlide(currentPage + 1);      };
    sio.previousSlide  = function() { changeSlide(currentPage - 1);      };
    sio.firstSlide     = function() { changeSlide(1);                    };
    sio.lastSlide      = function() { changeSlide(pdf.pdfInfo.numPages); };

    sio.syncAudience   = updateAudience;
    sio.update         = updateUI;

    $(window).resize(updateUI);

    return sio;

})(); });
