import { Fragment, useRef, useState } from "react";
import { useMount, useUpdateEffect } from "react-use";
import { motion } from "framer-motion";
import saveAsPng from "save-svg-as-png";

import { EditorType, IconItem } from "types/editor";
import Shapes from "@/components/svg/shapes";
import { Icons } from "components/svg/icons";
import { Null } from "components/svg/shapes/null";

export const Icon = ({
  editor,
  size = 200,
  id,
  onChange,
  onChangeTab,
}: {
  editor: EditorType;
  id?: string;
  size?: number;
  onChange?: (e: EditorType) => void;
  onChangeTab?: (e: number) => void;
}) => {
  const shapeRef = useRef<any>(null);
  const ComponentShape =
    Shapes[editor.shape?.component as keyof typeof Shapes] ?? Null;

  return (
    <ComponentShape
      ref={shapeRef}
      width={size}
      height={size}
      shape={editor.shape}
      id={id}
    >
      {editor?.icons?.map((icon, k) => {
        const findIcon = Icons?.find(
          (i: IconItem) => icon.component === i.name
        );
        const customText = icon?.custom_text?.enabled;
        const customImage = icon?.image;
        const GradientType =
          icon?.gradient?.type === "radialGradient"
            ? "radialGradient"
            : "linearGradient";
        if (!findIcon && !customText && !customImage) return null;
        return (
          <Fragment key={k}>
            <defs>
              <GradientType
                id={`icon-gradient-${k}`}
                gradientTransform={`rotate(${icon?.gradient?.angle ?? "90"})`}
              >
                {icon?.gradient?.enabled ? (
                  <>
                    {icon?.gradient?.colours?.map((color, c) => (
                      <stop
                        key={c}
                        offset={`${color.left}%`}
                        stopColor={
                          editor?.shape?.transparency ? "#000" : color.value
                        }
                      />
                    ))}
                  </>
                ) : (
                  <stop
                    offset="0%"
                    stopColor={
                      editor?.shape?.transparency ? "#000" : icon.colour
                    }
                  />
                )}
              </GradientType>
            </defs>
            <_IconComponent
              component={findIcon?.component}
              shapeRef={shapeRef}
              shape={editor?.shape?.component}
              key={k}
              index={k}
              icon={icon}
              onChange={(e: any) =>
                onChange &&
                onChange({
                  ...editor,
                  icons: editor.icons.map((i: any, index: number) =>
                    index === k ? e : i
                  ),
                })
              }
              onClick={onChangeTab ? () => onChangeTab(2) : undefined}
            />
          </Fragment>
        );
      })}
    </ComponentShape>
  );
};

const _IconComponent = ({
  shapeRef,
  component,
  icon,
  shape,
  index,
  onChange,
  ...props
}: any) => {
  const iconRef = useRef<any>(null);
  const [position, setPosition] = useState<any>(null);

  useUpdateEffect(() => {
    const position = setIconPosition(iconRef, shapeRef);
    setPosition(position);
    const svg = document.getElementById("discotools-selected-svg");
    saveAsPng.svgAsPngUri(svg).then(() => {});
  }, [shapeRef.current, icon.component, icon?.image]);

  useMount(() => {
    const position = setIconPosition(iconRef, shapeRef);
    setPosition(position);
  });

  useUpdateEffect(() => {
    onChange({
      ...icon,
      position,
    });
  }, [position]);

  const IconComponent = component as any;

  return (
    <motion.g
      animate={{
        x: icon?.position?.x ?? position?.x ?? 0,
        y: icon?.position?.y ?? position?.y ?? 0,
        scale: icon?.position?.scale ?? 1,
        rotate: icon?.position?.angle ?? 0,
        originX: 0.5,
        filter:
          icon?.shadow?.enabled &&
          `drop-shadow(${icon?.shadow?.position?.x}px ${icon?.shadow?.position?.y}px ${icon?.shadow?.position?.blur}px ${icon?.shadow?.colour})`,
      }}
      fill={`url(#${`icon-gradient-${index}`})`}
      stroke={icon?.border?.colour}
      strokeLinejoin="round"
      strokeWidth={icon?.border?.width}
      style={{
        transformOrigin: "center",
        // filter: `drop-shadow(${icon?.shadow?.position?.x}px ${icon?.shadow?.position?.y}px ${icon?.shadow?.position?.blur}px ${icon?.shadow?.colour})`,
      }}
    >
      {icon?.custom_text?.enabled ? (
        <text
          ref={iconRef as any}
          style={{
            fontSize: icon?.custom_text?.size
              ? `${icon?.custom_text?.size}px`
              : "100px",
            fontWeight: 900,
          }}
          className="font-title"
          viewBox="0 0 200 -100"
        >
          {icon?.custom_text?.text}
        </text>
      ) : icon?.image ? (
        <image
          ref={iconRef as any}
          href={icon?.image}
          width={190}
          height={190}
          viewBox="0 0 190 190"
          preserveAspectRatio="xMidYMid slice"
        />
      ) : (
        <IconComponent ref={iconRef} {...props} />
      )}
    </motion.g>
  );
};

const setIconPosition = (iconRef: any, shapeRef: any) => {
  if (iconRef?.current) {
    const shapeBoxW = shapeRef?.current?.getAttribute("viewBox")?.split(" ")[2];
    const shapeBoxH = shapeRef?.current?.getAttribute("viewBox")?.split(" ")[3];
    const iconBoxW = iconRef?.current?.getAttribute("viewBox")?.split(" ")[2];
    const iconBoxH = iconRef?.current?.getAttribute("viewBox")?.split(" ")[3];

    const position = {
      x: shapeBoxW / 2 - iconBoxW / 2,
      y: shapeBoxH / 2 - iconBoxH / 2,
      xPath: Number(shapeBoxW - iconBoxW),
      yPath: Number(shapeBoxH - iconBoxH),
    };
    return position;
  }
};
