import { fabric } from "fabric";
import {
  clearObjects,
  sortObjects,
  transformHighlightedText,
  checkTextBoxHeight,
} from "../../components/canvas/utils";
import { PaddedHighlightingTextbox } from "../../components/canvas/textbox";

let textBox = null;

let backgroundRect = null;
let arrow = null;

let contractedByTextbox = null;

let logoImage = null;
let previousLogoPosition = null;

const redraw = async (canvas, options) => {
  clearObjects([textBox, contractedByTextbox, backgroundRect, arrow], canvas);

  const logoWidth = Math.ceil(canvas.width * 0.23);
  const logoSideMargin = Math.ceil(canvas.width * 0.07);
  const logoTopMargin = Math.ceil(canvas.width * 0.155);

  const textBoxWidth = Math.ceil(canvas.width * 0.8);
  const textBoxMarginSide = Math.ceil(canvas.width * 0.13);
  const textBoxMarginTop = logoTopMargin + Math.ceil(canvas.height * 0.15);
  const textSize = Math.ceil(canvas.height * 0.07);
  const textLineHeight = 1;

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

  const arrowWidth = Math.ceil(canvas.width * 0.047);
  const arrowHeight = Math.ceil(canvas.width * 0.055);
  const arrowThickness = Math.ceil(canvas.width * 0.019);
  const arrowMarginLeft = Math.ceil(canvas.width * 0.07);
  const arrowMarginLeftExtra = Math.ceil(canvas.width * -0.01);
  const arrowMarginTop = Math.ceil(canvas.height * 0.017);

  canvas.preserveObjectStacking = true;

  /* BEGIN Background render */

  backgroundRect = new fabric.Rect({
    width: canvas.width * 1.1,
    height: canvas.height * 1.1,
    top: -20, // FIXME: Why???? Fabric.js, what are you trying to tell me?!
    left: -20,
    fill: options.colors.background.value,
    selectable: false,
    zIndex: 0,
  });

  canvas.add(backgroundRect);

  /* END Background render */

  /* BEGIN Logo render */

  // A logo is provided, and it either hasn't been rendered yet or is a new one.
  const createNewLogo =
    (options.logoImage !== null &&
      (logoImage === null ||
        (options.logoImage !== null &&
          options.logoImage !== logoImage._element))) ||
    previousLogoPosition != options.logoPosition.id;

  previousLogoPosition = options.logoPosition.id;

  if (createNewLogo) {
    canvas.remove(logoImage);

    logoImage = new fabric.Image(options.logoImage, { selectable: false });
    logoImage.scaleToWidth(logoWidth);

    if (options.logoPosition.id == "top-right") {
      logoImage.set({
        left: canvas.width - logoWidth - logoSideMargin,
        top: logoTopMargin,
        zIndex: 11,
      });
    } else if (options.logoPosition.id == "top-left") {
      logoImage.set({
        left: logoSideMargin,
        top: logoTopMargin,
        zIndex: 11,
      });
    } else if (options.logoPosition.id == "bottom-left") {
      logoImage.set({
        left: logoSideMargin,
        top: canvas.height - logoTopMargin - logoImage.getScaledHeight(),
        zIndex: 11,
      });
    } else {
      logoImage.set({
        left: canvas.width - logoWidth - logoSideMargin,
        top: canvas.height - logoTopMargin - logoImage.getScaledHeight(),
        zIndex: 11,
      });
    }

    canvas.add(logoImage);
  }

  /* END Logo render */

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

    const highlightedData = transformHighlightedText(
      options.mainText,
      textSize,
      textBoxWidth,
      "Bebas Neue",
      options.colors.highlight.value,
      options.colors.highlightedText.value,
      { padWhenDiacritics: true },
    );

    const textBoxTop = textBoxMarginTop;

    textBox = new PaddedHighlightingTextbox(highlightedData.text, {
      width: canvas.width,
      left: textBoxMarginSide,
      top: textBoxTop - highlightedData.paddingBottom,
      textAlign: "left",
      fontFamily: "Bebas Neue",
      fontSize: textSize,
      lineHeight: textLineHeight,
      fill: options.colors.baseText.value,
      styles: highlightedData.styles,
      selectable: false,
      highlightPadding: canvas.height * 0.003,
      zIndex: 10,
    });

    checkTextBoxHeight(textBox, 7);

    canvas.add(textBox);

    /* END Text render */

    /* BEGIN Contracted by render */

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

      checkTextBoxHeight(contractedByTextbox, 1);

      canvas.add(contractedByTextbox);
    }

    /* END Contracted by render */

    /* BEGIN Arrow render */

    arrow = new fabric.Polygon(
      [
        { x: 0, y: 0 },
        { x: arrowThickness, y: 0 },
        {
          x: arrowWidth,
          y: Math.ceil(arrowHeight) / 2,
        },
        {
          x: arrowThickness,
          y: arrowHeight,
        },
        { x: 0, y: arrowHeight },
        {
          x: arrowWidth - arrowThickness,
          y: Math.ceil(arrowHeight) / 2,
        },
        { x: 0, y: 0 },
      ],
      {
        top: textBoxTop + arrowMarginTop,
        left:
          arrowMarginLeft +
          (options.mainText[0] === "*" ? arrowMarginLeftExtra : 0),
        fill: options.colors.arrow.value,
        selectable: false,
        zIndex: 10,
      },
    );

    canvas.add(arrow);

    /* END Arrow render */
  }

  sortObjects(canvas);
};

export default redraw;
