'use client';

import { GemSmoke, gemSmokePresets } from '@paper-design/shaders-react';
import { useControls, button, folder } from 'leva';
import { setParamsSafe, useResetLevaParams } from '@/helpers/use-reset-leva-params';
import { usePresetHighlight } from '@/helpers/use-preset-highlight';
import { cleanUpLevaParams } from '@/helpers/clean-up-leva-params';
import { gemSmokeMeta, GemSmokeShapes, GemSmokeShape } from '@paper-design/shaders';
import { ShaderFit } from '@paper-design/shaders';
import { levaDeleteImageButton, levaImageButton } from '@/helpers/leva-image-button';
import { useState, Suspense, useEffect, useCallback } from 'react';
import { ShaderDetails } from '@/components/shader-details';
import { ShaderContainer } from '@/components/shader-container';
import { useUrlParams } from '@/helpers/use-url-params';
import { gemSmokeDef } from '@/shader-defs/gem-smoke-def';
import { toHsla } from '@/helpers/color-utils';
import { useColors } from '@/helpers/use-colors';

const { worldWidth, worldHeight, ...defaults } = gemSmokePresets[0].params;

const imageFiles = [
  'contra.svg',
  'apple.svg',
  'paradigm.svg',
  'paper-logo-only.svg',
  'brave.svg',
  'capy.svg',
  'infinite.svg',
  'linear.svg',
  'mercury.svg',
  'mymind.svg',
  'resend.svg',
  'shopify.svg',
  'wealth-simple.svg',
  'chanel.svg',
  'cibc.svg',
  'cloudflare.svg',
  'discord.svg',
  'nasa.svg',
  'nike.svg',
  'volkswagen.svg',
  'diamond.svg',
] as const;

const GemSmokeWithControls = () => {
  const [imageIdx, setImageIdx] = useState(-1);
  const [image, setImage] = useState<HTMLImageElement | string>('');

  useEffect(() => {
    if (imageIdx >= 0) {
      const name = imageFiles[imageIdx];
      const img = new Image();
      img.src = `/images/logos/${name}`;
      img.onload = () => setImage(img);
    }
  }, [imageIdx]);

  const handleClick = useCallback(() => {
    setImageIdx((prev) => (prev + 1) % imageFiles.length);
    // setImageIdx(() => Math.floor(Math.random() * imageFiles.length));
  }, []);

  const { colors, setColors } = useColors({
    defaultColors: defaults.colors,
    maxColorCount: gemSmokeMeta.maxColorCount,
  });

  const [params, setParams] = useControls(() => {
    return {
      colorBack: { value: toHsla(defaults.colorBack), order: 100 },
      colorInner: { value: toHsla(defaults.colorInner), order: 101 },
      shape: {
        value: defaults.shape,
        options: Object.keys(GemSmokeShapes) as GemSmokeShape[],
        order: 102,
        disabled: Boolean(image),
      },
      innerDistortion: { value: defaults.innerDistortion, min: 0, max: 1, order: 201 },
      outerDistortion: { value: defaults.outerDistortion, min: 0, max: 1, order: 202 },
      outerGlow: { value: defaults.outerGlow, min: 0, max: 1, order: 203 },
      innerGlow: { value: defaults.innerGlow, min: 0, max: 1, order: 204 },
      offset: { value: defaults.offset, min: -1, max: 1, order: 205 },
      angle: { value: defaults.angle, min: 0, max: 360, order: 250 },
      size: { value: defaults.size, min: 0, max: 1, order: 251 },
      speed: { value: defaults.speed, min: 0, max: 4, order: 300 },
      scale: { value: defaults.scale, min: 0.1, max: 4, order: 301 },
      Image: folder({
        'Upload image': levaImageButton((img?: HTMLImageElement) => setImage(img ?? '')),
        ...(image && { 'Delete image': levaDeleteImageButton(() => setImage('')) }),
      }, { order: -1 }),
    };
  }, [colors.length, image]);

  useControls(() => {
    const presets = Object.fromEntries(
      gemSmokePresets.map(({ name, params: { worldWidth, worldHeight, ...preset } }) => [
        name,
        button(() => {
          const { colors, ...presetParams } = preset;
          setColors(colors);
          setParamsSafe(params, setParams, presetParams);
        }),
      ])
    );
    return {
      Presets: folder(presets, { order: -2 }),
    };
  });

  // Reset to defaults on mount, so that Leva doesn't show values from other
  // shaders when navigating (if two shaders have a color1 param for example)
  useResetLevaParams(params, setParams, defaults);
  useUrlParams(params, setParams, gemSmokeDef, setColors);
  usePresetHighlight(gemSmokePresets, params);
  cleanUpLevaParams(params);

  return (
    <>
      <ShaderContainer shaderDef={gemSmokeDef} currentParams={params}>
        <Suspense fallback={null}>
          <GemSmoke onClick={handleClick} {...params} colors={colors} image={image} suspendWhenProcessingImage />
        </Suspense>
      </ShaderContainer>
      <ShaderDetails
        shaderDef={gemSmokeDef}
        currentParams={{ colors, ...params }}
        codeSampleImageName="images/logos/diamond.svg"
      />
    </>
  );
};

export default GemSmokeWithControls;
