import React, { useState } from 'react';
import { StyleSheet, TouchableWithoutFeedback } from 'react-native';
import { SBox } from '../s-components/layout/s-box';
import { ShadowBox } from './shadow-box';
import { SImage } from '../s-components/s-image';
import { SGradientCard } from '../s-components/s-gradient-card';
import { TCssRules } from '../types';
import { fp as _ } from '../utils/fp';

type TProps = TCssRules & {
  variant?: 'simple' | 'shadow' | 'no-shadow';
  containerStyle?:
    | {
        tapped: TCssRules;
        default: TCssRules;
      }
    | TCssRules;
  bgStyle?:
    | {
        tapped: TCssRules;
        default: TCssRules;
      }
    | TCssRules;
  gradient?:
    | {
        tapped: { colors: string[]; opacity?: number };
        default: { colors: string[]; opacity?: number };
      }
    | { colors: string[]; opacity?: number };
  renderBody?: (pressed: boolean) => any;
  onPress?: () => void;
  bgImage?: string;
  renderWave?: (pressed: boolean) => React.ReactElement;
  testID?: string;
  children: React.ReactNode;
};

export const TouchableCard: React.FC<TProps> = props => {
  const [pressed, setPressed] = useState(false);

  const {
    children,
    variant,
    containerStyle,
    bgStyle,
    gradient,
    renderBody,
    onPress,
    bgImage,
    renderWave,
    ...rest
  } = props;

  const tappedContainerStyle = _.path('tapped', containerStyle);
  const defaultContainerStyle = _.path('default', containerStyle);
  const tappedBgStyle = _.path('tapped', bgStyle);
  const defaultBgStyle = _.path('default', bgStyle);
  const tappedGradient = _.path('tapped', gradient);
  const defaultGradient = _.path('default', gradient);

  const activeContainerStyle = !defaultContainerStyle
    ? containerStyle
    : pressed
    ? tappedContainerStyle
    : defaultContainerStyle;
  const activeBgStyle = !defaultBgStyle
    ? bgStyle
    : pressed
    ? tappedBgStyle
    : defaultBgStyle;
  const activeGradient = !defaultGradient
    ? gradient
    : pressed
    ? tappedGradient
    : defaultGradient;
  const hasGradient = !!gradient;
  let content = null;

  const innerContent = (
    <SBox
      position="relative"
      flex={1}
      overflow="hidden"
      borderRadius={rest.borderRadius}
    >
      <SBox
        style={[StyleSheet.absoluteFill]}
        borderRadius={rest.borderRadius}
        {...activeBgStyle}
      >
        {bgImage ? (
          <SImage
            height={rest.height}
            borderRadius={rest.borderRadius}
            source={{ uri: bgImage }}
          />
        ) : null}
        {hasGradient ? (
          <SGradientCard
            colors={activeGradient!.colors}
            width={1}
            borderRadius={rest.borderRadius}
            opacity={activeGradient!.opacity}
          />
        ) : null}
        {renderWave ? renderWave(pressed) : null}
      </SBox>
      <SBox flex={1}>{children}</SBox>
    </SBox>
  );

  if (variant === 'simple') {
    content = (
      <SBox {...rest} {...activeContainerStyle}>
        {renderBody ? renderBody(pressed) : children}
      </SBox>
    );
  } else if (variant === 'shadow') {
    content = (
      <SBox {...rest} {...activeContainerStyle} height={rest.height}>
        <ShadowBox height={rest.height}>{innerContent}</ShadowBox>
      </SBox>
    );
  } else if (variant === 'no-shadow') {
    content = (
      <SBox {...rest} {...activeContainerStyle} height={rest.height}>
        {innerContent}
      </SBox>
    );
  }

  return (
    <TouchableWithoutFeedback
      onPressIn={() => {
        setPressed(true);
      }}
      onPressOut={() => {
        setPressed(false);
      }}
      onPress={() => {
        if (onPress) {
          onPress();
        }
      }}
    >
      {content}
    </TouchableWithoutFeedback>
  );
};

TouchableCard.defaultProps = {
  variant: 'simple',
};
