import BaseText from "../../blocks/BaseText";
import * as React from "react";
import { View, StyleSheet } from "react-native";

type CSSVal = string | number;
import Blocks from "../../components/blocks/blocks";
import DynamicDiv from "../../components/dynamic-div";
import DynamicRenderer from "../../components/dynamic-renderer/dynamic-renderer";
import InlinedStyles from "../../components/inlined-styles";
import type { SizeName } from "../../constants/device-sizes";
import { getSizesForBreakpoints } from "../../constants/device-sizes";
import { TARGET } from "../../constants/target";
import { deoptSignal } from "../../functions/deopt";
import { getClassPropName } from "../../functions/get-class-prop-name";
import { mapStyleObjToStrIfNeeded } from "../../functions/get-style";
import type { Dictionary } from "../../types/typescript";
import type { Column, ColumnProps } from "./columns.types";
import { getColumnsClass } from "./helpers";

function Columns(props: ColumnProps) {
  function gutterSize() {
    return typeof props.space === "number" ? props.space || 0 : 20;
  }

  function cols() {
    return props.columns || [];
  }

  function stackAt() {
    return props.stackColumnsAt || "tablet";
  }

  function getTagName(column: Column) {
    return column.link ? props.builderLinkComponent || BaseText : View;
  }

  function getWidth(index: number) {
    return cols()[index]?.width || 100 / cols().length;
  }

  function getColumnCssWidth(index: number) {
    const width = getWidth(index);
    const subtractWidth = gutterSize() * (cols().length - 1) * (width / 100);
    return `calc(${width}% - ${subtractWidth}px)`;
  }

  function getTabletStyle({
    stackedStyle,
    desktopStyle,
  }: {
    stackedStyle: CSSVal;
    desktopStyle: CSSVal;
  }) {
    return stackAt() === "tablet" ? stackedStyle : desktopStyle;
  }

  function getMobileStyle({
    stackedStyle,
    desktopStyle,
  }: {
    stackedStyle: CSSVal;
    desktopStyle: CSSVal;
  }) {
    return stackAt() === "never" ? desktopStyle : stackedStyle;
  }

  function flexDir() {
    return props.stackColumnsAt === "never"
      ? "row"
      : props.reverseColumnsWhenStacked
      ? "column-reverse"
      : "column";
  }

  function columnsCssVars() {
    return {
      flexDirection: flexDir() as "row" | "column" | "column-reverse",
    };
  }

  function columnCssVars(index: number) {
    const gutter = index === 0 ? 0 : gutterSize();
    const width = getColumnCssWidth(index);
    const gutterPixels = `${gutter}px`;
    const mobileWidth = "100%";
    const mobileMarginLeft = 0;
    const marginLeftKey = "margin-left";
    const sharedStyles = {
      display: "flex",
      flexDirection: "column",
      alignItems: "stretch",
    };
    return {
      ...sharedStyles,
      marginLeft: props.stackColumnsAt === "never" ? gutter : 0,
    } as any as Dictionary<string>;
  }

  function getWidthForBreakpointSize(size: SizeName) {
    const breakpointSizes = getSizesForBreakpoints(
      props.builderContext.content?.meta?.breakpoints || {}
    );
    return breakpointSizes[size].max;
  }

  function columnsStyles() {
    const childColumnDiv = `.${props.builderBlock.id}-breakpoints > .builder-column`;
    return `
        @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
          .${props.builderBlock.id}-breakpoints {
            flex-direction: var(--flex-dir-tablet);
            align-items: stretch;
          }

          ${childColumnDiv} {
            width: var(--column-width-tablet) !important;
            margin-left: var(--column-margin-left-tablet) !important;
          }
        }

        @media (max-width: ${getWidthForBreakpointSize("small")}px) {
          .${props.builderBlock.id}-breakpoints {
            flex-direction: var(--flex-dir);
            align-items: stretch;
          }

          ${childColumnDiv} {
            width: var(--column-width-mobile) !important;
            margin-left: var(--column-margin-left-mobile) !important;
          }
        },
      `;
  }

  function getAttributes(column: any, index: number) {
    return {
      ...{
        dataSet: {
          "builder-block-name": "builder-column",
        },
      },
      ...(column.link
        ? {
            href: column.link,
          }
        : {}),
      [getClassPropName()]: "builder-column",
      style: mapStyleObjToStrIfNeeded(columnCssVars(index)),
    };
  }

  return (
    <View
      style={{
        ...styles.view1,
        ...columnsCssVars(),
      }}
      {...{
        dataSet: {
          "builder-block-name": "builder-columns",
        },
      }}
    >
      {TARGET !== "reactNative" ? (
        <InlinedStyles
          id="builderio-columns"
          styles={columnsStyles()}
          nonce={props.builderContext.nonce}
        />
      ) : null}
      {props.columns?.map((column, index) => (
        <DynamicRenderer
          key={index}
          TagName={getTagName(column)}
          actionAttributes={{}}
          attributes={getAttributes(column, index)}
        >
          <Blocks
            path={`columns.${index}.blocks`}
            parent={props.builderBlock.id}
            context={props.builderContext}
            registeredComponents={props.builderComponents}
            linkComponent={props.builderLinkComponent}
            blocks={column.blocks}
            styleProp={{
              flexGrow: 1,
            }}
          />
        </DynamicRenderer>
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  view1: { display: "flex", height: "100%" },
});

export default Columns;
