/**
 * Relabi controls
 * @module src/ui/Controls.jsx;
 */

import * as React from "react";
import { useCallback, useRef } from "react";

import Slider from "rc-slider";
import TooltipSlider, { handleRender } from "./TooltipSlider.tsx";
import "rc-slider/assets/index.css";

const WAVE_SHAPE_NAMES = ["sine", "triangle", "saw", "reverse_saw", "square"];

export default function Controls({ relabi }) {
  /**
   * Handle updating a slider
   */
  const onChange = useCallback(
    (type, index) => (value) => {
      if (type === "bound") {
        relabi.bounds[index].level = value;
      }
      if (type === "shape") {
        relabi.waves[index].shape = WAVE_SHAPE_NAMES[value];
      }
      if (type === "frequency") {
        relabi.waves[index].frequency = Math.exp(value);
      }
      if (type === "weight") {
        relabi.waves[index].weight = value;
      }
      if (type === "settings") {
        relabi.settings[index] = index === "speed" ? Math.exp(value) : value;
      }
    },
    [relabi]
  );

  if (!relabi) {
    return null;
  }

  return (
    <ControlRow>
      <ControlBox>
        <Label>Bounds</Label>
        <SliderRow>
          {relabi?.bounds.map((bound, index) => (
            <ControlSlider
              rel={`bound_${index}`}
              type="bound"
              index={index}
              onChange={onChange}
              min={-1}
              max={1}
              step={0.01}
              tipFormatter={(value) => -value}
              defaultValue={bound.level}
              color={bound.color}
              reverse
            />
          ))}
        </SliderRow>
      </ControlBox>

      <ControlBox>
        <Label>Wave frequencies</Label>
        <SliderRow>
          {relabi?.waves.map((wave, index) => (
            <ControlSlider
              rel={`frequency_${index}`}
              type="frequency"
              index={index}
              onChange={onChange}
              min={-2}
              max={3}
              step={0.001}
              defaultValue={Math.log(wave.frequency)}
              tipFormatter={(value) => Math.exp(value).toFixed(1)}
              color={"#8a8"}
            />
          ))}
        </SliderRow>
      </ControlBox>

      <ControlBox>
        <Label>Wave shapes</Label>
        <SliderRow>
          {relabi?.waves.map((wave, index) => (
            <ControlSlider
              rel={`shape_${index}`}
              type="shape"
              index={index}
              onChange={onChange}
              min={0}
              max={WAVE_SHAPE_NAMES.length - 1}
              step={1}
              defaultValue={WAVE_SHAPE_NAMES.indexOf(wave.shape)}
              color={"#aa8"}
              tipFormatter={(value) => WAVE_SHAPE_NAMES[value]}
            />
          ))}
        </SliderRow>
      </ControlBox>

      <ControlBox>
        <Label>Wave weights</Label>
        <SliderRow>
          {relabi?.waves.map((wave, index) => (
            <ControlSlider
              rel={`weight_${index}`}
              type="weight"
              index={index}
              onChange={onChange}
              min={0}
              max={2}
              step={0.01}
              defaultValue={wave.weight}
              color={"#99b"}
            />
          ))}
        </SliderRow>
      </ControlBox>

      <ControlBox>
        <Label>Speed</Label>
        <SliderRow>
          <ControlSlider
            type="settings"
            index="speed"
            onChange={onChange}
            min={-2}
            max={3}
            step={0.01}
            defaultValue={Math.log(relabi.settings.speed)}
            tipFormatter={(value) => Math.exp(value).toFixed(1)}
            color={"#a88"}
          />
        </SliderRow>
      </ControlBox>

      <ControlBox>
        <Label>Chaos</Label>
        <SliderRow>
          <ControlSlider
            type="settings"
            index="feedback"
            onChange={onChange}
            min={0}
            max={0.5}
            step={0.01}
            defaultValue={relabi.settings.feedback}
            color={"#a88"}
          />
        </SliderRow>
      </ControlBox>
    </ControlRow>
  );
}

/**
 * UI Elements
 */
const ControlRow = ({ children }) => (
  <div
    style={{
      display: "flex",
      flexDirection: "row",
      marginTop: "1rem",
    }}
  >
    {children}
  </div>
);

const ControlBox = ({ children }) => (
  <div
    style={{
      marginLeft: "1rem",
    }}
  >
    {children}
  </div>
);

const SliderRow = ({ children }) => (
  <div
    style={{
      display: "flex",
      flexDireciton: "row",
      height: "10rem",
      marginTop: "0.5rem",
    }}
  >
    {children}
  </div>
);

const Label = ({ children }) => (
  <div style={{ fontSize: "0.75rem" }}>{children}</div>
);

const ControlSlider = ({
  type,
  index,
  min,
  max,
  step,
  reverse,
  defaultValue,
  color,
  onChange,
  tipFormatter,
}) => (
  <div style={{ marginRight: "0.5rem" }}>
    <TooltipSlider
      vertical
      min={min}
      max={max}
      step={step}
      reverse={reverse}
      defaultValue={defaultValue}
      onChange={onChange(type, index)}
      handleStyle={{
        backgroundColor: color,
        borderColor: color,
        opacity: 1,
      }}
      trackStyle={{ backgroundColor: "#888", width: "2px" }}
      railStyle={{ backgroundColor: "#888", width: "2px" }}
      tipFormatter={tipFormatter || ((value) => value)}
    />
  </div>
);
