import React, { forwardRef, useMemo } from "react";
import { View as RNView, ViewProps } from "react-native";

import theme from "mazlo-theme";

import styledComponent from "../../utils/styledComponent";
import styles from "./styles";

export type Props = {
  as?: string;
  children?: React.ReactNode;
  onMouseEnter?: () => void;
  onMouseLeave?: () => void;
  p?: number;
  pb?: number;
  pl?: number;
  pr?: number;
  pt?: number;
  px?: number;
  py?: number;
  m?: number;
  mb?: number;
  ml?: number;
  mr?: number;
  mt?: number;
  mx?: number;
  my?: number;
  row?: boolean;
  flex?: number | boolean;
} & ViewProps;

const StyledView = styledComponent<ViewProps>(RNView);

const View = forwardRef<typeof StyledView, Props>(
  (
    {
      as,
      p,
      pb,
      pl,
      pr,
      pt,
      px,
      py,
      m,
      mb,
      ml,
      mr,
      mt,
      mx,
      my,
      row,
      flex,
      style = null,
      ...props
    }: Props,
    forwardedRef
  ) => {
    const viewStyle = useMemo(
      () => [
        styles.view,
        row && styles.row,
        flex != null && {
          flex: flex === true ? 1 : flex,
        },
        as && theme.styles[as],
        p && { padding: theme.space[p] },
        px && { paddingHorizontal: theme.space[px] },
        py && { paddingVertical: theme.space[py] },
        pt && { paddingTop: theme.space[pt] },
        pr && { paddingRight: theme.space[pr] },
        pb && { paddingBottom: theme.space[pb] },
        pl && { paddingLeft: theme.space[pl] },
        m && { margin: theme.space[m] },
        mx && { marginHorizontal: theme.space[mx] },
        my && { marginVertical: theme.space[my] },
        mt && { marginTop: theme.space[mt] },
        mr && { marginRight: theme.space[mr] },
        mb && { marginBottom: theme.space[mb] },
        ml && { marginLeft: theme.space[ml] },
        ...[].concat(style),
      ],
      [
        row,
        flex,
        as,
        p,
        pb,
        pl,
        pr,
        pt,
        px,
        py,
        m,
        mb,
        ml,
        mr,
        mt,
        mx,
        my,
        style,
      ]
    );

    return <StyledView style={viewStyle} ref={forwardedRef} {...props} />;
  }
);

View.displayName = "View";

export default View;
