import React, { useCallback, useEffect, useState, useRef } from 'react';
import {
  Animated,
  Keyboard,
  Platform,
  StyleSheet,
  TouchableWithoutFeedback,
} from 'react-native';
import { debounceTime, take, tap } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { SBox } from '../s-components/layout/s-box';
import { STextInput } from '../s-components/s-text-input';
import { Icon } from './icon';
import { theme } from '../../app/theme';
import { fp as _ } from '../utils/fp';
import { SBoxAnimated } from '../s-components/layout/s-box-animated';
import { scrollNamedSubject$ } from '../utils/scroll-service';
import { TIconName } from '../types';
import { throttleAuditTime } from '../utils/rx/operators';

export const inputFocus$ = new BehaviorSubject(false);

type TProps = {
  disabled?: boolean;
  placeholder: string;
  iconName?: TIconName;
  input?: {
    onChange: (s: string) => void;
    value: string;
  };
  onChange?: (s: string) => void;
  onFocus?: () => void;
  onBlur?: () => void;
  value?: string;
  forwardedRef: any;
  placeholderTextColor?: string;
  bg?: string;
  animation?: Record<string, Animated.AnimatedInterpolation<any>>;
  onFocusBeforeScroll: () => void | boolean;
  isScrolled?: boolean;
  blurOnScroll?: boolean;
  variant: string;
};

const InputComponent: React.FC<TProps> = props => {
  const [inFocus, setInFocus] = useState(false);
  const {
    disabled,
    iconName,
    placeholder,
    forwardedRef,
    input,
    value,
    onChange,
    placeholderTextColor,
    bg,
    animation,
    onFocus,
    onFocusBeforeScroll,
    variant,
    onBlur,
    blurOnScroll,
    isScrolled,
  } = props;
  const isTextarea = variant === 'textarea';
  const isIos = Platform.OS === 'ios';
  const androidTextareaHeight = inFocus ? 85 : 143;
  const textareaHeight = isIos ? 143 : androidTextareaHeight;
  const subscription = useRef();

  const blurField = useCallback(() => {
    if (forwardedRef.current) {
      forwardedRef.current.blur();
    }
  }, [forwardRef]);

  useEffect(() => {
    const scrollSub = scrollNamedSubject$
      .pipe(throttleAuditTime(100))
      .subscribe(() => {
        // fix for lists with keyboard on android
        if (Platform.OS === 'android') {
          Keyboard.dismiss();
        }
        if (blurOnScroll) {
          blurField();
        }
      });

    return () => {
      scrollSub.unsubscribe();
    };
  }, [blurOnScroll]);

  const onFocusCallback = useCallback(() => {
    setInFocus(true);
    inputFocus$.next(true);
    if (onFocus) {
      onFocus();
    }
  }, [onFocus]);

  const onBlurCallback = useCallback(() => {
    setInFocus(false);
    inputFocus$.next(false);
    if (onBlur) {
      onBlur();
    }
  }, [onBlur]);

  const onScroll = (fn: () => void) => {
    // @ts-ignore
    subscription.current = scrollNamedSubject$
      .pipe(
        debounceTime(100),
        take(1),
        tap(() => {
          subscription.current = undefined;
        })
      )
      .subscribe(fn);
  };

  const focusField = useCallback(() => {
    if (forwardedRef.current) {
      forwardedRef.current.focus();
    }
  }, [forwardRef]);

  const onClear = useCallback(() => {
    if (input && input.onChange) {
      input.onChange('');
    } else if (onChange) {
      onChange('');
    }

    if (isScrolled) {
      onScroll(focusField);
    } else {
      focusField();
    }
  }, [input, onChange, isScrolled]);

  if (isTextarea) {
    return (
      <SBoxAnimated style={animation} borderRadius={8} bg={bg} width={1}>
        <STextInput
          style={{
            height: textareaHeight,
            paddingTop: 7,
            paddingHorizontal: 16,
            paddingBottom: 12,
          }}
          ref={forwardedRef}
          placeholder={placeholder}
          value={value || (input && input.value)}
          selectionColor={theme.colors.wildStrawberry}
          underlineColorAndroid="transparent"
          onChangeText={onChange || (input && input.onChange)}
          onFocus={onFocusCallback}
          onBlur={onBlurCallback}
          editable={!disabled}
          spellCheck={false}
          autoCorrect={false}
          placeholderTextColor={placeholderTextColor}
          allowFontScaling={false}
          numberOfLines={6}
          multiline
          textAlignVertical="top"
        />
      </SBoxAnimated>
    );
  }

  return (
    <SBoxAnimated
      style={animation}
      borderRadius={22}
      bg={bg}
      height={44}
      width={1}
      pt={13}
      pl={iconName ? 45 : 20}
      pr={44}
      position="relative"
    >
      {_.isFunction(onFocusBeforeScroll) ? (
        <TouchableWithoutFeedback
          onPress={() => {
            if (subscription.current) return;
            onScroll(() => {
              if (forwardedRef.current) {
                forwardedRef.current.focus();
              }
            });
            onFocusBeforeScroll();
          }}
        >
          <SBox
            style={StyleSheet.absoluteFill}
            bg={theme.colors.transparent}
            zIndex={2}
          />
        </TouchableWithoutFeedback>
      ) : null}
      <SBox />
      {iconName ? (
        <SBox position="absolute" top={11} left={11}>
          <Icon name={iconName} color="lavenderGray" size={21} />
        </SBox>
      ) : null}
      <STextInput
        ref={forwardedRef}
        placeholder={inFocus ? '' : placeholder}
        value={value || (input && input.value)}
        selectionColor={theme.colors.wildStrawberry}
        underlineColorAndroid="transparent"
        onChangeText={onChange || (input && input.onChange)}
        onFocus={onFocusCallback}
        onBlur={onBlurCallback}
        editable={!disabled}
        spellCheck={false}
        autoCorrect={false}
        placeholderTextColor={placeholderTextColor}
        allowFontScaling={false}
      />
      {/* @ts-ignore */}
      {_.length(value) ? (
        <TouchableWithoutFeedback testID="clear-search" onPress={onClear}>
          <SBox
            position="absolute"
            top={0}
            right={0}
            height={44}
            width={44}
            pt={11}
            pl={11}
            zIndex={3}
          >
            <Icon name="close" color="lavenderGray" size={21} />
          </SBox>
        </TouchableWithoutFeedback>
      ) : null}
    </SBoxAnimated>
  );
};

InputComponent.defaultProps = {
  disabled: false,
  bg: 'white',
  animation: {},
};

function forwardRef(props: any, ref: any) {
  return <InputComponent {...props} forwardedRef={ref} />;
}

export const Input = React.forwardRef(forwardRef);
