//
//  Pointer2D.js
//  CoverPage
//
//  Created by Richard Anaya on 1/9/2013.
//  Copyright (c) 2014 Evernote. All rights reserved.
//

var Pointer2D = function() {
    var _this = this;
    this.canvas = document.createElement('canvas');
    $encpJquery(this.canvas).css('position','fixed');
    $encpJquery(this.canvas).css('cursor','none');
    $encpJquery(this.canvas).css('top','0px');
    $encpJquery(this.canvas).css('left','0px');
    $encpJquery(this.canvas).css('z-index','9999999999');
    $encpJquery(document.body).append(this.canvas);

    $encpJquery(window).resize(_.bind(this.onWindowResize,this));
    this.onWindowResize();

    //prevent i-beam cursor
    $encpJquery(_this.canvas).get(0).onselectstart = function () { return false; };
    this.canvasLogic($encpJquery(this.canvas));

    this.cursorColors = {
        "blue": "#0090F4",
        "green": "#C0E23C",
        "pink": "#F7478E",
        "none": null
    };
    this.currentColor = "green";

    this.FPS = 30;
	
	$encpJquery('.pointer-container').css("pointer-events","none");
    $encpJquery(_this.canvas).css("pointer-events","none");
	$encpJquery('html').css('cursor','none');
    $encpJquery('body').css('cursor','none');
};

Pointer2D.prototype.clear = function() {

}

Pointer2D.prototype.changeCursor = function(type) {
    var _this = this;
    localStorage.setItem("cursorType",type);
    this.currentCursor = type;
    if(type == "default"){
        this.isVisible = false;
        this.hide();
        $encpJquery('html').css('cursor','default');
        $encpJquery('body').css('cursor','default');
    }
    else {
        this.isVisible = true;
        this.show();
        $encpJquery('html').css('cursor','none');
        $encpJquery('body').css('cursor','none');
        if(type == "blue"){
            _this.currentColor = "blue"
        }
        else if(type == "red"){
            _this.currentColor = "pink"
        }
        else if(type == "yellow"){
            _this.currentColor = "green"
        }
    }
}

Pointer2D.prototype.render = function() {
}


Pointer2D.prototype.onWindowResize = function() {
    $encpJquery(this.canvas).css('width',window.innerWidth+'px');
    $encpJquery(this.canvas).css('height',window.innerHeight+'px');
};

/* Pointer canvas logic */
Pointer2D.prototype.canvasLogic = function(canvas) {
    var _this = this;
    //canvas.addClass("disallow-autofade").fadeIn(ENCPW.ui.fadeSpeed);
    canvas.tail = [];
    canvas.tailMax = 10;
    /* Used to kill all animations and resume regular lasering */
    canvas.killAnimation = false;
    /* Is true when there's a tail fade-out onging */
    canvas.fadeOutAnimOngoing = false;
    var ctx = canvas[0].getContext("2d");
    var dotRadius = 8;

    var drawTail = function() {
        ctx.beginPath();

        var x, y, x2, y2, xc, yc, distance, angle;

        x = canvas.tail[0].x;
        y = canvas.tail[0].y;
        x2 = canvas.tail[canvas.tail.length - 1].x;
        y2 = canvas.tail[canvas.tail.length - 1].y;
        distance = Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2));
        angle = Math.atan(dotRadius / distance);

        /* From tail of tip to one edge of circle */
        ctx.setTransform(1, 0, 0, 1, 0, 0);

        var rotationAxisX = canvas.tail[0].x;
        var rotationAxisY = canvas.tail[0].y;

        ctx.translate(rotationAxisX, rotationAxisY);
        ctx.rotate(angle);

        var x = canvas.tail[canvas.tail.length - 1].x - rotationAxisX;
        var y = canvas.tail[canvas.tail.length - 1].y - rotationAxisY;
        var xc, yc, x2, y2;

        ctx.moveTo(x, y);

        var i = canvas.tail.length - 1;
        for (; i > 0; i--) {
            x = canvas.tail[i].x - rotationAxisX;
            y = canvas.tail[i].y - rotationAxisY;
            x2 = canvas.tail[i - 1].x - rotationAxisX;
            y2 = canvas.tail[i - 1].y - rotationAxisY;

            xc = (x + x2) / 2;
            yc = (y + y2) / 2;

            ctx.quadraticCurveTo(x, y, xc, yc);
        }

        if (i != 0) {
            x = canvas.tail[i].x - rotationAxisX;
            y = canvas.tail[i].y - rotationAxisY;
            x2 = canvas.tail[i - 1].x - rotationAxisX;
            y2 = canvas.tail[i - 1].y - rotationAxisY;

            ctx.quadraticCurveTo(x, y, x2, y2);
        }

        /* From other edge of circle back to tip of tail */
        ctx.setTransform(1, 0, 0, 1, 0, 0);

        var rotationAxisX = canvas.tail[0].x;
        var rotationAxisY = canvas.tail[0].y;

        ctx.translate(rotationAxisX, rotationAxisY);
        ctx.rotate(-angle);

        var x = canvas.tail[0].x - rotationAxisX;
        var y = canvas.tail[0].y - rotationAxisY;
        var xc, yc, x2, y2;

        ctx.lineTo(x, y);

        var i = 1;
        for (; i < canvas.tail.length - 2; i++) {
            x = canvas.tail[i].x - rotationAxisX;
            y = canvas.tail[i].y - rotationAxisY;
            x2 = canvas.tail[i + 1].x - rotationAxisX;
            y2 = canvas.tail[i + 1].y - rotationAxisY;

            xc = (x + x2) / 2;
            yc = (y + y2) / 2;

            ctx.quadraticCurveTo(x, y, xc, yc);
        }

        if (i != canvas.tail.length - 1 && i > 1) {
            x = canvas.tail[i].x - rotationAxisX;
            y = canvas.tail[i].y - rotationAxisY;
            x2 = canvas.tail[i + 1].x - rotationAxisX;
            y2 = canvas.tail[i + 1].y - rotationAxisY;

            ctx.quadraticCurveTo(x, y, x2, y2);
        }

        ctx.closePath();
        ctx.lineWidth = 2;
        ctx.strokeStyle = "white";
        ctx.fillStyle = _this.cursorColors[_this.currentColor];
        ctx.fill();
        ctx.stroke();
    };

    var drawHead = function() {
        if(!_this.isVisible){
            return;
        }
        /* Main dot background */
        var x = canvas.tail[canvas.tail.length - 1].x;
        var y = canvas.tail[canvas.tail.length - 1].y;
        ctx.setTransform(1, 0, 0, 1, 0, 0);

        ctx.beginPath();
        ctx.arc(x, y, dotRadius, 0, Math.PI*2, true);
        ctx.fillStyle = "#FFFFFF";
        ctx.closePath();
        ctx.fill();

        /* Main dot ring */
        ctx.beginPath();
        ctx.arc(x, y, dotRadius, 0, Math.PI*2, true);
        ctx.lineWidth = 1;
        ctx.strokeStyle = _this.cursorColors[_this.currentColor];
        ctx.closePath();
        ctx.stroke();

        /* Main dot inner fill */
        ctx.beginPath();
        ctx.arc(x, y, dotRadius * 0.75, 0, Math.PI*2, true);
        ctx.lineWidth = 0;
        ctx.fillStyle = _this.cursorColors[_this.currentColor];
        ctx.closePath();
        ctx.fill();
    };

    var fadeOutTail = function(startTime, animTime, callback) {
        if (canvas.fadeOutAnimOngoing === false) {
            canvas.fadeOutAnimOngoing = true;
            canvas.killAnimation = false;
        }
        var timeSpent = (new Date()).getTime() - startTime;
        var timeFactor = timeSpent / animTime;
        var alpha = Math.round((1 - timeFactor) * 100) / 100;

        /* Immediate abort */
        if (canvas.killAnimation === true && canvas.fadeOutAnimOngoing === true) {
            ctx.globalAlpha = 1;
            canvas.killAnimation = false;
            canvas.fadeOutAnimOngoing = false;
            return;
        }

        if (alpha > 0) {
            ctx.globalAlpha = alpha;
            ctx.clearRect(0, 0, canvas[0].width, canvas[0].height);
            //drawTail();
            ctx.globalAlpha = 1;
            drawHead();

            this.setTimeout(function() {
                fadeOutTail(startTime, animTime, callback);
            },1000/this.FPS);
        } else {
            var tmpTail = [];
            tmpTail.push(canvas.tail[canvas.tail.length - 1]);
            canvas.tail = tmpTail;

            ctx.clearRect(0, 0, canvas[0].width, canvas[0].height);
            //drawTail();
            ctx.globalAlpha = 1;
            drawHead();

            if (callback != null) {
                callback();
            }

            canvas.fadeOutAnimOngoing = false;
        }
    };

    var lastCursorColour = "green";
    var fadeOutTimer = null;
    
	$encpJquery(document).on('mousemove',function(e) {
        /* This handles changing cursor type / colour -- done this way to avoid
         * changing/checking css too often, or clearing too often */
        if (_this.currentColor !== lastCursorColour) {
            if (_this.currentColor === "none") {
                ctx.clearRect(0,0, canvas[0].width, canvas[0].height);
                canvas.css("cursor", "auto");
                lastCursorColour = _this.currentColor;
                return;
            } else {
                canvas.css("cursor", "none");
                lastCursorColour = _this.currentColor;
            }
        }

        if (_this.currentColor === "none") {
            return;
        }

        canvas.killAnimation = true;
        clearTimeout(fadeOutTimer);
        fadeOutTimer = setTimeout(function() {
            fadeOutTail((new Date()).getTime(), 500);
        }, 500);

        var x = e.clientX;
        var y = e.clientY;

        canvas.tail.push({x: x, y: y});
        if (canvas.tail.length > canvas.tailMax) {
            canvas.tail.shift();
        }

        ctx.setTransform(1, 0, 0, 1, 0, 0);
        canvas.attr("height", "" + canvas.height() + "px");
        canvas.attr("width", "" + canvas.width() + "px");
        ctx.clearRect(0, 0, canvas.width(), canvas.height());

        //drawTail();
        drawHead();
    });

    /* Do exit animation when mouse leaves canvas (i.e. uses UI) */
    canvas.mouseout(function() {
        clearTimeout(fadeOutTimer);
        fadeOutTail((new Date()).getTime, 250, function() {
            ctx.clearRect(0, 0, canvas.width(), canvas.height());
        });
    });
};

Pointer2D.prototype.destroy = function(){
    $encpJquery(this.canvas).remove();
};

Pointer2D.prototype.show = function(){
    $encpJquery(this.canvas).show();
};

Pointer2D.prototype.hide = function(){
    $encpJquery(this.canvas).hide();
};