import { useEffect, useRef } from 'react';
import { Animated, Keyboard, Platform } from 'react-native';

function getInitialKeyboardHeight() {
  if (Platform.OS !== 'ios') {
    return 0;
  }

  /**
   * React Native 0.68.0 버전에는 `metrics()`가 존재하지 않아 분기 처리
   */
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  if (typeof Keyboard?.metrics === 'function') {
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    return Keyboard.metrics()?.height ?? 0;
  } else {
    return 0;
  }
}

/**
 * @category Hooks
 * @name useKeyboardAnimatedHeight
 * @description
 * 키보드가 나타나거나 사라질 때, 키보드의 높이의 변화를 애니메이션 가능한 값(`Animated.Value`)으로 반환하는 Hook이에요. 키보드가 올라오거나 내려갈 때 키보드 높이에 맞춰 UI 요소를 부드럽게 변화시킬 수 있어요.
 *
 * 이 Hook은 주로 iOS에서 사용해요. Android에서는 키보드 높이 변경을 감지하지 않고, 항상 초기값이 `0`인 `Animated.Value`를 반환해요. 즉, Android 환경에서는 애니메이션이 적용되지 않아요.
 *
 * @returns {Animated.Value} - 키보드의 높이를 나타내는 애니메이션 값이에요.
 * @example
 * ```typescript
 * const keyboardHeight = useKeyboardAnimatedHeight();
 *
 * <Animated.View style={{ marginBottom: keyboardHeight }}>
 *  {children}
 * </Animated.View>
 * ```
 */
export function useKeyboardAnimatedHeight(): Animated.Value {
  const keyboardHeight = useRef(new Animated.Value(getInitialKeyboardHeight())).current;

  useEffect(() => {
    if (Platform.OS === 'ios') {
      const willShowSubscription = Keyboard.addListener('keyboardWillShow', (event) => {
        const height = event.endCoordinates.height;

        Animated.spring(keyboardHeight, {
          toValue: height,
          useNativeDriver: true,
          ...spring.quick,
        }).start();
      });

      const willHideSubscription = Keyboard.addListener('keyboardWillHide', () => {
        Animated.spring(keyboardHeight, {
          toValue: 0,
          useNativeDriver: true,
          ...spring.quick,
        }).start();
      });
      return () => {
        willShowSubscription.remove();
        willHideSubscription.remove();
      };
    } else {
      return;
    }
  }, [keyboardHeight]);

  return keyboardHeight;
}

const spring = {
  quick: {
    stiffness: 800,
    damping: 55,
    mass: 1,
  },
};
