import { fabric } from "fabric";
import {
  clearObjects,
  sortObjects,
  transformHighlightedText,
  checkTextBoxHeight,
} from "../../components/canvas/utils";
import { PaddedHighlightingTextbox } from "../../components/canvas/textbox";
import backgroundURL from "../../assets/template/make_a_wish_banner/background.png";
import backgroundURLInverted from "../../assets/template/make_a_wish_banner/background_inverted.png";
import COLORS from "../../colors";

let mainTextBox = null;

let personNameText = null;
let personPositionText = null;

let mainImage = null;
let backgroundImage = null;
let previousBackgroundImageColor = null;

let contractedByTextbox = null;

let mainImageSource = null;

const redraw = async (canvas, options) => {
  clearObjects(
    [
      mainTextBox,
      personNameText,
      personPositionText,
      contractedByTextbox,
    ],
    canvas,
  );

  canvas.preserveObjectStacking = true;

  const textMarginLeft = Math.ceil(canvas.width * 0.24);
  const textMarginRight = Math.ceil(canvas.width * 0.2);

  let mainTextMarginBottom = Math.ceil(canvas.height * 0.05);
  const mainTextBackgroundMarginTop = Math.ceil(canvas.height * 0.14);
  const mainTextSize = Math.ceil(canvas.height * 0.07);
  const mainTextHeightLimit = Math.ceil(mainTextSize * 3.3);
  const mainTextLineHeight = 1;

  const bottomTextSize = Math.ceil(canvas.height * 0.035);
  const positionTextSize = Math.ceil(canvas.height * 0.025);
  const nameTextMarginBottom = Math.ceil(canvas.height * 0.1);
  const nameTextMarginLeft = Math.ceil(canvas.width * 0.05);
  const nameTextExtraBottomMargin = Math.ceil(canvas.height * 0.05);
  const nameTextMaxWidth = Math.ceil(canvas.width * 0.15);
  const positionTextSideGap = nameTextMarginLeft;
  const positionTextMarginBottom = Math.ceil(canvas.height * 0.06);
  const positionTextSeparatorWidth = Math.ceil(canvas.width * 0.0035);
  const positionTextMaxWidth = Math.ceil(canvas.width * 0.15);

  const contractedByTextSize = Math.ceil(canvas.height * 0.02);
  const contractedByTextMaxWidth = Math.ceil(canvas.width * 0.9);
  const contractedByTextSidesMargin = Math.ceil(canvas.width * 0.03);

  if (options.mainText !== null) {
    /* BEGIN Background render */

    if (backgroundImage === null || options.colors.background.value != previousBackgroundImageColor.value) {
      backgroundImage = new Image();

      await new Promise((resolve) => {
        backgroundImage.onload = () => {
          resolve();
        };

        if (options.colors.background.value == COLORS.black.value) {
          backgroundImage.src = backgroundURL;
        } else {
          backgroundImage.src = backgroundURLInverted;
        }
      });

      backgroundImage = new fabric.Image(backgroundImage, {
        top: canvas.height - backgroundImage.height, // FIXME: Why???? Fabric.js, what are you trying to tell me?!
        left: -20,
        zIndex: 10,
        selectable: false,
      });
      backgroundImage.scaleToWidth(canvas.width + 22);

      previousBackgroundImageColor = options.colors.background;

      canvas.add(backgroundImage);
    }

    /* END Background render */


    /* BEGIN Name text render */

    if (options.personName !== null) {
      let styles = {
        0: {},
      };

      /*
      for (let position = 0; position < options.personName.length; position++) {
        styles[0][position] = {
          fontWeight: "bold",
        };
      }
      */

      personNameText = new fabric.Textbox(options.personName, {
        left: nameTextMarginLeft,
        top: canvas.height - bottomTextSize - nameTextMarginBottom,
        width: nameTextMaxWidth,
        fontFamily: "Bebas Neue",
        fontSize: bottomTextSize,
        styles: styles,
        fill: options.colors.nameText.value,
        selectable: false,
        zIndex: 20,
      });

      checkTextBoxHeight(personNameText, 1);

      if (options.personPosition !== null) {
        personPositionText = new fabric.Textbox(options.personPosition, {
          left: positionTextSideGap,
          top: canvas.height - bottomTextSize - positionTextMarginBottom,
          width: positionTextMaxWidth,
          fontFamily: "Roboto Condensed",
          fontSize: positionTextSize,
          fill: options.colors.baseText.value,
          selectable: false,
          zIndex: 20,
        });

        checkTextBoxHeight(personPositionText, 1);

        if (personPositionText._textLines.length === 2) {
          mainTextMarginBottom += nameTextExtraBottomMargin;
          personNameText.set({
            top: personNameText.top - nameTextExtraBottomMargin,
          });
          personPositionText.set({
            top: personPositionText.top - nameTextExtraBottomMargin,
          });
        }

        canvas.add(personPositionText);

        canvas.renderAll();
      }

      canvas.add(personNameText);
    }

    /* END Name text render */

    /* BEGIN Main text render */

    const mainTextWidth = canvas.width - textMarginLeft - textMarginRight;

    const highlightedData = transformHighlightedText(
      options.mainText,
      mainTextSize,
      mainTextWidth,
      "Bebas Neue",
      options.colors.highlight.value,
      options.colors.highlightedText.value,
      { padWhenDiacritics: false, invertHighlight: true },
    );

    mainTextBox = new PaddedHighlightingTextbox(highlightedData.text, {
      width: canvas.width,
      left: textMarginLeft,
      textAlign: "left",
      fontFamily: "Bebas Neue",
      fontSize: mainTextSize,
      lineHeight: mainTextLineHeight,
      fill: options.colors.baseText.value,
      styles: highlightedData.styles,
      selectable: false,
      highlightPadding: canvas.height * 0.003,
      zIndex: 20,
    });

    checkTextBoxHeight(mainTextBox, 1);

    canvas.add(mainTextBox);

    const mainTextBoxTop =
      canvas.height - mainTextBox.height - mainTextMarginBottom;

    mainTextBox.top = mainTextBoxTop - highlightedData.paddingBottom;

    canvas.renderAll();

    /* END Main text render */
  }

  /* BEGIN Contracted by render */

  if (options.contractedBy !== null) {
    contractedByTextbox = new fabric.Textbox(options.contractedBy, {
      left: contractedByTextSidesMargin,
      top: contractedByTextSidesMargin,
      width: contractedByTextMaxWidth,
      fontFamily: "Roboto Condensed",
      fontSize: contractedByTextSize,
      textAlign: "left",
      fill: options.colors.contractedByText.value,
      selectable: false,
      zIndex: 20,
    });

    checkTextBoxHeight(contractedByTextbox, 1);

    canvas.add(contractedByTextbox);
  }

  /* END Contracted by render */

  /* BEGIN Main image render */

  if (
    options.mainImage !== null &&
    (!canvas.contains(mainImage) ||
      mainImage === null ||
      options.mainImage.src !== mainImageSource)
  ) {
    if (mainImage !== null) {
      canvas.remove(mainImage);
    }

    mainImage = new fabric.Image(options.mainImage, {
      left: 0,
      top: 0,
      zIndex: 0,
    });

    mainImage.controls = {
      ...fabric.Image.prototype.controls,
      mtr: new fabric.Control({ visible: false }),
    };

    if (mainImage.width >= mainImage.height) {
      mainImage.scaleToHeight(canvas.height);
    } else {
      mainImage.scaleToWidth(canvas.width);
    }

    canvas.add(mainImage);
    mainImageSource = options.mainImage.src;
    // canvas.centerObject(mainImage)
  } else if (mainImage !== null && options.mainImage === null) {
    canvas.remove(mainImage);
  }

  /* END Main image render */

  sortObjects(canvas);
};

export default redraw;
