import { useEffect, useRef, useCallback, useState } from 'react';
import { mergeLeft } from 'ramda';
import { useSigmaContext } from '@react-sigma/core';
import { getPixelRatio } from 'sigma/utils';
import { isEmptyValue } from '@reltio/mdm-sdk';
var createCanvasContext = function (canvas) {
    var contextOptions = { preserveDrawingBuffer: false, antialias: false };
    return canvas.getContext('2d', contextOptions);
};
var createCanvas = function (id) {
    var canvas = document.createElement('canvas');
    canvas.style.position = 'absolute';
    canvas.setAttribute('class', "sigma-".concat(id));
    return canvas;
};
export var useSigmaCustomRenderers = function () {
    var _a = useSigmaContext(), container = _a.container, sigma = _a.sigma;
    var _b = useState({}), renderers = _b[0], setRenderers = _b[1];
    var canvasesRef = useRef({});
    var widthRef = useRef(0);
    var heightRef = useRef(0);
    var addRenderers = useCallback(function (renderers) {
        setRenderers(mergeLeft(renderers));
    }, []);
    var resize = useCallback(function () {
        widthRef.current = container.offsetWidth;
        heightRef.current = container.offsetHeight;
        var pixelRatio = getPixelRatio();
        for (var id in canvasesRef.current) {
            var _a = canvasesRef.current[id], canvas = _a.canvasElement, context = _a.context;
            canvas.style.width = widthRef.current + 'px';
            canvas.style.height = heightRef.current + 'px';
            canvas.setAttribute('width', widthRef.current * pixelRatio + 'px');
            canvas.setAttribute('height', heightRef.current * pixelRatio + 'px');
            if (pixelRatio !== 1) {
                context.scale(pixelRatio, pixelRatio);
            }
        }
    }, [container.offsetHeight, container.offsetWidth]);
    var afterRender = useCallback(function () {
        for (var id in renderers) {
            var context = canvasesRef.current[id].context;
            context.clearRect(0, 0, widthRef.current, heightRef.current);
            var renderer = renderers[id].renderer;
            renderer(context);
        }
    }, [renderers]);
    var beforeRender = useCallback(function () {
        for (var id in renderers) {
            var shouldCreateCanvas = isEmptyValue(canvasesRef.current[id]);
            if (!shouldCreateCanvas)
                continue;
            var insertBefore = renderers[id].insertBefore;
            var sigmaContainer = container.querySelector('.sigma-container');
            var canvas = createCanvas(id);
            var context = createCanvasContext(canvas);
            sigmaContainer.insertBefore(canvas, sigmaContainer.querySelector(".sigma-".concat(insertBefore)));
            canvasesRef.current[id] = { canvasElement: canvas, context: context };
            resize();
        }
    }, [renderers, container, resize]);
    useEffect(function () {
        sigma.addListener('beforeRender', beforeRender);
        return function () {
            sigma.off('beforeRender', beforeRender);
        };
    }, [sigma, beforeRender]);
    useEffect(function () {
        sigma.addListener('afterRender', afterRender);
        return function () {
            sigma.off('afterRender', afterRender);
        };
    }, [sigma, afterRender]);
    useEffect(function () {
        sigma.addListener('resize', resize);
        return function () {
            sigma.off('resize', resize);
        };
    }, [sigma, resize]);
    useEffect(function () {
        var canvases = canvasesRef.current;
        return function () {
            for (var id in canvases) {
                var canvas = canvases[id];
                canvas.canvasElement.remove();
                delete canvases[id];
            }
        };
    }, []);
    return { addRenderers: addRenderers, canvases: canvasesRef.current, canvasesRef: canvasesRef };
};
