import React, { useEffect } from 'react';

const AnimatedBackground = () => {
    useEffect(() => {
        var canvas = document.querySelectorAll('#bg canvas'),
            background = canvas[0],
            foreground1 = canvas[1],
            foreground2 = canvas[2],
            config = {
                star: {
                    amount: 18,
                    layer: 3,
                    color: [157, 97, 207],
                    alpha: 0.3
                },
                line: {
                    amount: 12,
                    layer: 3,
                    color: [255, 255, 255],
                    alpha: 0.3
                },
                speed: 0.5,
                angle: 20
            };

        if (background.getContext) {
            var bctx = background.getContext('2d'),
                fctx1 = foreground1.getContext('2d'),
                fctx2 = foreground2.getContext('2d'),
                M = window.Math, // Cached Math
                degree = config.angle / 360 * M.PI * 2,
                stars = [],
                lines = [],
                wWidth, wHeight, timer;

            var setCanvasHeight = function () {
                wWidth = window.innerWidth;
                wHeight = window.innerHeight;

                canvas.forEach(function (item) {
                    item.width = wWidth;
                    item.height = wHeight;
                });
            };

            var drawStar = function (x, y, radius, color, alpha) {
                fctx1.beginPath();
                fctx1.moveTo(x, y - radius);

                for (var i = 0; i < 5; i++) {
                    fctx1.lineTo(x + Math.sin((i * 2 * Math.PI) / 5) * radius, y - Math.cos((i * 2 * Math.PI) / 5) * radius);
                    fctx1.lineTo(x + Math.sin(((i + 0.5) * 2 * Math.PI) / 5) * (radius / 2), y - Math.cos(((i + 0.5) * 2 * Math.PI) / 5) * (radius / 2));
                }

                fctx1.closePath();

                var gradient = fctx1.createRadialGradient(x, y, radius, x, y, 0);
                gradient.addColorStop(0, 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + alpha + ')');
                gradient.addColorStop(1, 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + (alpha - 0.1) + ')');

                fctx1.fillStyle = gradient;
                fctx1.fill();
            };

            var drawLine = function (x, y, width, color, alpha) {
                var endX = x + M.sin(degree) * width,
                    endY = y - M.cos(degree) * width,
                    gradient = fctx2.createLinearGradient(x, y, endX, endY);
                gradient.addColorStop(0, 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + alpha + ')');
                gradient.addColorStop(1, 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + (alpha - 0.1) + ')');

                fctx2.beginPath();
                fctx2.moveTo(x, y);
                fctx2.lineTo(endX, endY);
                fctx2.lineWidth = 3;
                fctx2.lineCap = 'round';
                fctx2.strokeStyle = gradient;
                fctx2.stroke();
            };

            var drawBack = function () {
                bctx.clearRect(0, 0, wWidth, wHeight);

                var gradient = [];

                gradient[0] = bctx.createRadialGradient(wWidth * 0.3, wHeight * 0.1, 0, wWidth * 0.3, wHeight * 0.1, wWidth * 0.9);
                gradient[0].addColorStop(0, '#1ab7e5');
                gradient[0].addColorStop(1, 'transparent');

                bctx.translate(wWidth, 0);
                bctx.scale(-1, 1);
                bctx.beginPath();
                bctx.fillStyle = gradient[0];
                bctx.fillRect(0, 0, wWidth, wHeight);

                gradient[1] = bctx.createRadialGradient(wWidth * 0.1, wHeight * 0.1, 0, wWidth * 0.3, wHeight * 0.1, wWidth);
                gradient[1].addColorStop(0, '#090d00');
                gradient[1].addColorStop(0.8, 'transparent');

                bctx.translate(wWidth, 0);
                bctx.scale(-1, 1);
                bctx.beginPath();
                bctx.fillStyle = gradient[1];
                bctx.fillRect(0, 0, wWidth, wHeight);

                gradient[2] = bctx.createRadialGradient(wWidth * 0.1, wHeight * 0.5, 0, wWidth * 0.1, wHeight * 0.5, wWidth * 0.5);
                gradient[2].addColorStop(0, '#a0349f');
                gradient[2].addColorStop(1, 'transparent');

                bctx.beginPath();
                bctx.fillStyle = gradient[2];
                bctx.fillRect(0, 0, wWidth, wHeight);
            };

            var animate = function () {
                var sin = M.sin(degree),
                    cos = M.cos(degree);

                if (config.star.amount > 0 && config.star.layer > 0) {
                    fctx1.clearRect(0, 0, wWidth, wHeight);
                    for (var i = 0, starLen = stars.length; i < starLen; i++) {
                        var starItem = stars[i],
                            starX = starItem.x,
                            starY = starItem.y,
                            starRadius = starItem.radius,
                            starSpeed = starItem.speed;

                        if (starX > wWidth + starRadius) {
                            starX = -starRadius;
                        } else if (starX < -starRadius) {
                            starX = wWidth + starRadius;
                        } else {
                            starX += sin * starSpeed;
                        }

                        if (starY > wHeight + starRadius) {
                            starY = -starRadius;
                        } else if (starY < -starRadius) {
                            starY = wHeight + starRadius;
                        } else {
                            starY -= cos * starSpeed;
                        }

                        starItem.x = starX;
                        starItem.y = starY;
                        drawStar(starX, starY, starRadius, starItem.color, starItem.alpha);
                    }
                }

                if (config.line.amount > 0 && config.line.layer > 0) {
                    fctx2.clearRect(0, 0, wWidth, wHeight);
                    for (var j = 0, lineLen = lines.length; j < lineLen; j++) {
                        var lineItem = lines[j],
                            lineX = lineItem.x,
                            lineY = lineItem.y,
                            lineWidth = lineItem.width,
                            lineSpeed = lineItem.speed;

                        if (lineX > wWidth + lineWidth * sin) {
                            lineX = -lineWidth * sin;
                        } else if (lineX < -lineWidth * sin) {
                            lineX = wWidth + lineWidth * sin;
                        } else {
                            lineX += sin * lineSpeed;
                        }

                        if (lineY > wHeight + lineWidth * cos) {
                            lineY = -lineWidth * cos;
                        } else if (lineY < -lineWidth * cos) {
                            lineY = wHeight + lineWidth * cos;
                        } else {
                            lineY -= cos * lineSpeed;
                        }

                        lineItem.x = lineX;
                        lineItem.y = lineY;
                        drawLine(lineX, lineY, lineWidth, lineItem.color, lineItem.alpha);
                    }
                }

                timer = requestAnimationFrame(animate);
            };

            var createItem = function () {
                stars = [];
                lines = [];

                if (config.star.amount > 0 && config.star.layer > 0) {
                    for (var i = 0; i < config.star.amount / config.star.layer; i++) {
                        for (var j = 0; j < config.star.layer; j++) {
                            stars.push({
                                x: M.random() * wWidth,
                                y: M.random() * wHeight,
                                radius: M.random() * (20 + j * 5) + (20 + j * 5),
                                color: config.star.color,
                                alpha: M.random() * 0.2 + (config.star.alpha - j * 0.1),
                                speed: config.speed * (1 + j * 0.5)
                            });
                        }
                    }
                }

                if (config.line.amount > 0 && config.line.layer > 0) {
                    for (var m = 0; m < config.line.amount / config.line.layer; m++) {
                        for (var n = 0; n < config.line.layer; n++) {
                            lines.push({
                                x: M.random() * wWidth,
                                y: M.random() * wHeight,
                                width: M.random() * (20 + n * 5) + (20 + n * 5),
                                color: config.line.color,
                                alpha: M.random() * 0.2 + (config.line.alpha - n * 0.1),
                                speed: config.speed * (5 + n * 0.5)
                            });
                        }
                    }
                }

                cancelAnimationFrame(timer);
                timer = requestAnimationFrame(animate);
                drawBack();
            };

            var resizeHandler = function () {
                setCanvasHeight();
                createItem();
            };

            setCanvasHeight();
            createItem();

            window.addEventListener('resize', resizeHandler);

            return () => {
                window.removeEventListener('resize', resizeHandler);
            };
        }
    }, []);

    return (
        <div id="bg" className="animation-container">
            <canvas></canvas>
            <canvas></canvas>
            <canvas></canvas>
        </div>
    );
};

export default AnimatedBackground;
