import {
    docReady, downloadCanvasWithoutButton, getMousePos, pointDistance, roundedRandom
} from "canvas-common";




var canvas;
var ctx;
var drawn = {};
var mousePos = {};

var animationId;

var config = {
    size: {
        height: window.innerHeight,
        width: window.innerWidth
    },
    dotLines: {
        dotAmount: (window.innerHeight * window.innerWidth) / 4000,
        boxWidth: 50,
        boxHeight: 50,
        maxLinks: 10,
        mouseRange: 100,
        numberOfIncrements: 50,
        paused: false,
        showAll: false,
        minOpacity: 0.1,
        fps: 30,
        linkRange: 100
    }
};

var currentNum = 0;

var dots = [];


function createDots() {
    for (var i = 0; i < config.dotLines.dotAmount; i++) {
        var dot = {};
        dot.x = roundedRandom(config.size.width);
        dot.y = roundedRandom(config.size.height);
        dot.origin = {x: dot.x, y: dot.y};
        createTarget(dot);
        startDotMovement(dot);
        dot.num = currentNum++;
        dot.links = [];
        dots.push(dot);
    }
}


function createLines() {
    dots.forEach(function (linkingDot) {
        dots.forEach(function (linkedDot) {
            if (linkingDot.links.length >= config.dotLines.maxLinks || linkedDot.links.length >= config.dotLines.maxLinks) return;
            var dist = pointDistance(linkingDot, linkedDot);
            if (dist < config.dotLines.linkRange && linkedDot.links.indexOf(linkingDot) == -1) {
                linkingDot.links.push(linkedDot);
            }
        })
    })
}

function renderDot(dotToRender) {
    if (dotToRender.num in drawn) return;
    var mouseDistance = pointDistance(dotToRender, mousePos);
    if ((mouseDistance > config.dotLines.mouseRange || mouseDistance == undefined || isNaN(parseInt(mouseDistance))) && !config.dotLines.showAll) return;
    drawn[dotToRender.num] = 1;
    ctx.beginPath();
    ctx.moveTo(dotToRender.x, dotToRender.y);
    var alpha = Math.max(config.dotLines.minOpacity, 1 - (mouseDistance / config.dotLines.mouseRange));
    // in case we want to show everything with full opacity
    //var alpha = Math.max(!config.dotLines.showAll ? config.dotLines.minOpacity : 1, 1 - (mouseDistance / config.dotLines.mouseRange));
    ctx.fillStyle = 'rgba(255, 0, 0, ' + alpha + ')';
    ctx.arc(dotToRender.x, dotToRender.y, 3, 0, 2 * Math.PI);
    ctx.fill();
    ctx.beginPath();
    ctx.strokeStyle = 'rgba(255, 0, 0, ' + alpha + ')';
    dotToRender.links.forEach(function (tar) {
        ctx.moveTo(dotToRender.x, dotToRender.y);
        ctx.lineTo(tar.x, tar.y);
    });
    ctx.stroke();
    dotToRender.links.forEach(renderDot)
}

function createTarget(dot) {
    dot.target = {
        x: dot.origin.x - config.dotLines.boxWidth / 2 + roundedRandom(config.dotLines.boxWidth),
        y: dot.origin.y - config.dotLines.boxHeight / 2 + roundedRandom(config.dotLines.boxHeight)
    };
}
function startDotMovement(dot) {
    dot.targetReached = false;
    createTarget(dot);
    var dist = pointDistance(dot, dot.target);
    var vect = {
        x: dot.target.x - dot.x,
        y: dot.target.y - dot.y
    };
    vect.x /= dist;
    vect.y /= dist;
    dot.distRemaining = dist;
    dot.vect = vect;
}

function act(dot) {
    if (dot.targetReached) {
        startDotMovement(dot);
        dot.x += dot.vect.x * (dot.distRemaining / config.dotLines.numberOfIncrements);
        dot.y += dot.vect.y * (dot.distRemaining / config.dotLines.numberOfIncrements);
    } else {
        dot.x += dot.vect.x * (dot.distRemaining / config.dotLines.numberOfIncrements);
        dot.y += dot.vect.y * (dot.distRemaining / config.dotLines.numberOfIncrements);
        if (pointDistance(dot, dot.target) < 10) {
            dot.targetReached = true;
        }
    }

}

function renderDots() {
    drawn = {};
    ctx.clearRect(0, 0, config.size.width, config.size.height);
    dots.forEach(renderDot);
    dots.forEach(act);
    setTimeout(function () {
        if(!config.dotLines.paused) {
            animationId = requestAnimationFrame(renderDots);
        }
    }, 1000 / config.dotLines.fps)
}

function setMousePos(e) {
    mousePos = getMousePos(canvas, e);
}


function pause() {
    config.dotLines.paused = !config.dotLines.paused;
    if (!config.dotLines.paused) {
        animationId = requestAnimationFrame(renderDots);
    } else {
        cancelAnimationFrame(animationId);
    }
}

function showAll() {
    config.dotLines.showAll = !config.dotLines.showAll;
}


docReady(function () {
    canvas = document.getElementById('canvas');
    canvas.width = config.size.width;
    canvas.height = config.size.height;
    canvas.onmousemove = setMousePos;
    ctx = canvas.getContext("2d");

    createDots();
    createLines();
    requestAnimationFrame(renderDots);
});


function downloadCanvasDotlines() {
    downloadCanvasWithoutButton('dotLines', canvas);
}


window.downloadCanvasCommon = downloadCanvasDotlines;
window.pause = pause;
window.showAll = showAll;
