import {SCALE_MODES} from '@pixi/constants';
import {BaseTexture, extensions} from '@pixi/core';
import {Stage as PixiStage} from '@pixi/react';
import {createElement, useContext} from 'react';

import AssetsContext from '@/react/context/assets.js';
import ClientContext from '@/react/context/client.js';
import DebugContext from '@/react/context/debug.js';
import EcsContext from '@/react/context/ecs.js';
import MainEntityContext from '@/react/context/main-entity.js';
import RadiansContext from '@/react/context/radians.js';
import {RESOLUTION} from '@/util/constants.js';

import Ecs from './ecs.jsx';
import {ApplicationStageLayers, ApplicationStageLights} from './extensions.js';
import styles from './pixi.module.css';

BaseTexture.defaultOptions.scaleMode = SCALE_MODES.NEAREST;

extensions.add(
  ApplicationStageLayers,
  ApplicationStageLights,
);

const Contexts = [
  AssetsContext,
  ClientContext,
  DebugContext,
  EcsContext,
  MainEntityContext,
  RadiansContext,
];

const ContextBridge = ({children, render}) => {
  const contexts = Contexts.map(useContext);
  return render(
    <>
      {
        Contexts.reduce(
          (children, Context, i) => ([
            createElement(Context.Provider, {value: contexts[i], key: Context}, children)
          ]),
          children,
        )
      }
    </>
  );
};

export const Stage = ({children, ...props}) => {
  return (
    <ContextBridge
      render={(children) => <PixiStage {...props}>{children}</PixiStage>}
    >
      {children}
    </ContextBridge>
  );
};

export default function Pixi({applyFilters, camera, monopolizers, particleWorker, scale}) {
  return (
    <Stage
      className={styles.stage}
      width={RESOLUTION.x}
      height={RESOLUTION.y}
      options={{
        background: 0x0,
      }}
    >
      <Ecs
        applyFilters={applyFilters}
        camera={camera}
        monopolizers={monopolizers}
        particleWorker={particleWorker}
        scale={scale}
      />
    </Stage>
  );
}

