import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
import * as React from "react";
import { ImageStyle, StyleSheet, View, ViewStyle } from "react-native";

type BorderPosition = "inside" | "outside" | "center";

interface Props {
  style: ImageStyle | ViewStyle;
  borderPosition: BorderPosition;
  borderPaddingTop: number;
  borderPaddingRight: number;
  borderPaddingBottom: number;
  borderPaddingLeft: number;
  children: React.ReactNode;
}

const COLOR_TRANSPARENT = "transparent";

const styles = StyleSheet.create({
  container: {
    overflow: "visible",
    borderWidth: 0,
    borderColor: COLOR_TRANSPARENT,
  },
  border: {
    ...StyleSheet.absoluteFillObject,
    zIndex: 1,
  },
});

const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
  switch (borderPosition) {
    case "inside":
      return 0;
    case "center":
      return borderWidth / 2;
    case "outside":
      return borderWidth;
    default:
      return borderWidth;
  }
};

const Border = ({
  style,
  padding,
  borderPosition,
}: {
  style: ViewStyle;
  padding: ViewStyle;
  borderPosition: BorderPosition;
}) => {
  if (!borderPosition) {
    return null;
  }

  const borderWidth = toNumberWithDefaultZero(style.borderWidth);
  const containerPadding = getBorderPadding(borderPosition, borderWidth);

  const initialBorderRadius = toNumberWithDefaultZero(style.borderRadius);
  const paddingTop = toNumberWithDefaultZero(padding.paddingTop);
  const paddingRight = toNumberWithDefaultZero(padding.paddingRight);
  const paddingBottom = toNumberWithDefaultZero(padding.paddingBottom);
  const paddingLeft = toNumberWithDefaultZero(padding.paddingLeft);

  const borderRadiusStyle = initialBorderRadius
    ? {
        borderTopLeftRadius:
          initialBorderRadius +
          containerPadding +
          Math.min(paddingTop, paddingLeft),
        borderTopRightRadius:
          initialBorderRadius +
          containerPadding +
          Math.min(paddingTop, paddingRight),
        borderBottomLeftRadius:
          initialBorderRadius +
          containerPadding +
          Math.min(paddingBottom, paddingLeft),
        borderBottomRightRadius:
          initialBorderRadius +
          containerPadding +
          Math.min(paddingBottom, paddingRight),
      }
    : {
        borderTopLeftRadius: 0,
        borderTopRightRadius: 0,
        borderBottomLeftRadius: 0,
        borderBottomRightRadius: 0,
      };

  return (
    <View
      pointerEvents="none"
      style={{
        ...styles.border,
        right: -containerPadding - paddingRight,
        bottom: -containerPadding - paddingBottom,
        left: -containerPadding - paddingLeft,
        top: -containerPadding - paddingTop,
        borderWidth,
        borderColor: style.borderColor,
        ...borderRadiusStyle,
      }}
    />
  );
};

export const BorderContainerView = (props: Props) => {
  const {
    borderPosition,
    borderPaddingTop,
    borderPaddingRight,
    borderPaddingBottom,
    borderPaddingLeft,
    style,
    children,
  } = props;

  const padding =
    borderPosition === "outside"
      ? {
          paddingTop: borderPaddingTop,
          paddingRight: borderPaddingRight,
          paddingBottom: borderPaddingBottom,
          paddingLeft: borderPaddingLeft,
        }
      : {};

  return (
    <View pointerEvents="box-none" {...props} style={[style, styles.container]}>
      <Border style={style} padding={padding} borderPosition={borderPosition} />
      {children}
    </View>
  );
};
