import {Container} from '@pixi/react';
import {useEffect, useState} from 'react';

import {useEcs, useEcsTick} from '@/context/ecs.js';
import {useMainEntity} from '@/context/main-entity.js';
// import {useRadians} from '@/context/radians.js';
// import {TAU} from '@/util/math.js';

import Entities from './entities.jsx';
import TargetingGhost from './targeting-ghost.jsx';
import TargetingGrid from './targeting-grid.jsx';
import TileLayer from './tile-layer.jsx';
import Water from './water.jsx';

const NIGHTNESS = 0.1;

function calculateDarkness(hour) {
  let darkness = 0;
  if (hour >= 21 || hour < 4) {
    darkness = 0.8;
  }
  if (hour >= 4 && hour < 7) {
    darkness = 0.8 * ((7 - hour) / 3);
  }
  if (hour >= 18 && hour < 21) {
    darkness = 0.8 * ((3 - (21 - hour)) / 3);
  }
  return Math.floor(darkness * 1000) / 1000;
}

export default function Ecs({applyFilters, camera, monopolizers, scale}) {
  const [ecs] = useEcs();
  const [filters, setFilters] = useState([]);
  const [mainEntity] = useMainEntity();
  const [layers, setLayers] = useState([]);
  const [hour, setHour] = useState(10);
  const [night, setNight] = useState();
  const [projected, setProjected] = useState([]);
  const [position, setPosition] = useState({x: 0, y: 0});
  const [water, setWater] = useState();
  // const radians = useRadians();
  // const [sine, setSine] = useState();
  // useEffect(() => {
  //   async function buildSineFilter() {
  //     const {default: SineFilter} = await import('@/filters/horizontal-sine.js');
  //     const sine = new SineFilter();
  //     sine.frequency = 1;
  //     sine.magnitude = 3;
  //     setSine(sine);
  //   }
  //   buildSineFilter();
  // }, []);
  // useEffect(() => {
  //   if (!sine) {
  //     return;
  //   }
  //   const r = (radians / 8) % TAU;
  //   sine.offset = 6 * (camera.y + r);
  //   sine.magnitude = 2 * (r > Math.PI ? TAU - r : r);
  // }, [camera, radians, scale, sine]);
  useEffect(() => {
    async function buildNightFilter() {
      const {ColorMatrixFilter} = await import('@pixi/filter-color-matrix');
      class NightFilter extends ColorMatrixFilter {
        setIntensity(intensity) {
          const double = NIGHTNESS * 2;
          const half = NIGHTNESS / 2;
          const redDown = 1 - (intensity * (1 + double));
          const blueUp = 1 - (intensity * (1 - half));
          const scale = intensity * NIGHTNESS;
          this.uniforms.m = [
            redDown, -scale, 0, 0, 0,
            -scale, (1 - intensity), scale, 0, 0,
            0, scale, blueUp, 0, 0,
            0, 0, 0, 1, 0,
          ];
        }
      }
      setNight(new NightFilter());
    }
    buildNightFilter();
  }, []);
  useEffect(() => {
    if (night) {
      night.setIntensity(calculateDarkness(hour));
    }
  }, [hour, night]);
  useEcsTick((payload) => {
    const entity = ecs.get(mainEntity);
    for (const id in payload) {
      const update = payload[id];
      switch (id) {
        case '1': {
          const master = ecs.get(1);
          if (update.TileLayers) {
            setLayers(Object.values(master.TileLayers.$$layersProxies));
          }
          if (update.Time) {
            setHour(Math.round(ecs.get(1).Time.hour * 60) / 60);
          }
          if (update.Water) {
            setWater(master.Water.water);
          }
          break;
        }
      }
    }
    if (entity) {
      const {Direction, Position, Wielder} = entity;
      setPosition(Position.toJSON());
      setProjected(Wielder.activeItem()?.project(Position.tile, Direction.direction));
    }
  }, [ecs, mainEntity, scale]);
  useEffect(() => {
    setFilters(
      applyFilters
        ? [
          ...(false && night ? [night] : []),
          // ...(sine ? [sine] : []),
        ]
        : [],
    );
  }, [applyFilters, night])
  return (
    <Container
      scale={scale}
      x={-camera.x}
      y={-camera.y}
    >
      <Container
        filters={filters}
      >
        {layers.map((layer, i) => (
          <TileLayer
            filters={filters}
            key={i}
            tileLayer={layer}
          />
        ))}
      </Container>
      {water && layers[0] && (
        <Water
          tileLayer={layers[0]}
          water={water}
        />
      )}
      {projected && layers[0] && (
        <TargetingGrid
          tileLayer={layers[0]}
          x={position.x}
          y={position.y}
        />
      )}
      <Entities
        filters={filters}
        monopolizers={monopolizers}
      />
      {projected?.length > 0 && layers[0] && (
        <TargetingGhost
          projected={projected}
          tileLayer={layers[0]}
        />
      )}
    </Container>
  )
}
