import {RenderTexture} from '@pixi/core';
import {Container} from '@pixi/display';
import {BlurFilter} from '@pixi/filter-blur';
import {Graphics} from '@pixi/graphics';
import {PixiComponent, useApp} from '@pixi/react';
import {Sprite} from '@pixi/sprite';
import {useEffect, useState} from 'react';

const tileSize = {x: 16, y: 16};
const radius = 17;

function makeFade(renderer) {
  const fade = new Graphics();
  fade.beginFill(0xffffff);
  fade.alpha = 0.5;
  fade.drawCircle(
    tileSize.x * (radius / 2),
    tileSize.y * (radius / 2),
    ((tileSize.x + tileSize.y) / 2) * (radius * 0.35),
  )
  fade.filters = [new BlurFilter(((tileSize.x + tileSize.y) / 2) * 2.5)];
  const renderTexture = RenderTexture.create({
    width: tileSize.x * radius,
    height: tileSize.y * radius,
  });
  renderer.render(fade, {renderTexture});
  return new Sprite(renderTexture);
}

const TargetingGridInternal = PixiComponent('TargetingGrid', {
  create: ({app}) => {
    const fade = makeFade(app.renderer);
    const grid = new Graphics();
    const lineWidth = 1;
    grid.lineStyle(lineWidth, 0xffffff);
    for (let y = 0; y < radius; ++y) {
      for (let x = 0; x < radius; ++x) {
        grid.drawRect(
          (x * tileSize.x) + (lineWidth / 2),
          (y * tileSize.y) + (lineWidth / 2),
          tileSize.x,
          tileSize.y,
        );
      }
    }
    grid.mask = fade;
    const innerGrid = new Graphics();
    innerGrid.lineStyle(lineWidth, 0x777777);
    for (let y = 0; y < radius; ++y) {
      for (let x = 0; x < radius; ++x) {
        innerGrid.drawRect(
          (x * tileSize.x) + (lineWidth / 2) + 1,
          (y * tileSize.y) + (lineWidth / 2) + 1,
          tileSize.x - 2,
          tileSize.y - 2,
        );
      }
    }
    innerGrid.mask = fade;
    const container = new Container();
    container.addChild(fade, grid, innerGrid);
    return container;
  },
  applyProps: (container, oldProps, {entity, radians}) => {
    const pulse = (Math.cos(radians) + 1) * 0.5;
    const {Position: {x, y}} = entity;
    const tileX = x - (x % tileSize.x);
    const tileY = y - (y % tileSize.y);
    const gridX = (tileSize.x * (radius / 2));
    const gridY = (tileSize.y * (radius / 2));
    container.x = tileX + (tileSize.x / 2) - gridX;
    container.y = tileY + (tileSize.y / 2) - gridY;
    container.children[0].x = x % tileSize.x - (tileSize.x / 2) ;
    container.children[0].y = y % tileSize.y - (tileSize.y / 2) ;
    const color = Math.round(255 - (pulse * 255));
    container.children[2].tint = `rgb(${color}, ${color}, ${color})`;
  },
})

export default function TargetingGrid({entity}) {
  const app = useApp();
  const [radians, setRadians] = useState(0);
  useEffect(() => {
    const handle = setInterval(() => {
      setRadians((radians) => (radians + 0.1) % (Math.PI * 2))
    }, 50);
    return () => {
      clearInterval(handle);
    };
  }, []);
  return (
    <TargetingGridInternal
      app={app}
      entity={entity}
      radians={radians}
    />
  );
}
