import {useNavigation} from '@react-navigation/native';
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
import {
  Image,
  Keyboard,
  KeyboardAvoidingView,
  Platform,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
// @ts-ignore
import Pinchable from 'react-native-pinchable';
import Animated, {EasingNode} from 'react-native-reanimated';
import {SafeAreaView} from 'react-native-safe-area-context';
import Video from 'react-native-video';
import {useDispatch, useSelector, useStore} from 'react-redux';
import {TaggedUsersDrawer} from '.';
import {headerBarOptions} from '../../routes';
import {MomentContext} from '../../screens/profile/IndividualMoment';
import {deleteMomentTag, loadMomentTags} from '../../services';
import {loadUserMoments} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {MomentPostType, MomentTagType, ScreenType, UserType} from '../../types';
import {
  getTimePosted,
  navigateToProfile,
  normalize,
  SCREEN_HEIGHT,
  SCREEN_WIDTH,
} from '../../utils';
import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments';
import {AddComment} from '../comments';
import CommentsCount from '../comments/CommentsCount';
import {MomentTags} from '../common';
import {MomentMoreInfoDrawer, TaggAvatar} from '../profile';
import IndividualMomentTitleBar from './IndividualMomentTitleBar';
interface MomentPostProps {
  moment: MomentPostType;
  userXId: string | undefined;
  screenType: ScreenType;
  updateMomentViewCount: () => void;
}

const MomentPost: React.FC<MomentPostProps> = ({
  moment,
  userXId,
  screenType,
  updateMomentViewCount,
}) => {
  const navigation = useNavigation();
  const dispatch = useDispatch();
  const {userId: loggedInUserId, username: loggedInUsername} = useSelector(
    (state: RootState) => state.user.user,
  );
  const {user} = useSelector((state: RootState) =>
    userXId ? state.userX[screenType][userXId] : state.user,
  );
  const state: RootState = useStore().getState();
  const isOwnProfile = user.username === loggedInUsername;

  const [tags, setTags] = useState<MomentTagType[]>([]);
  const [tagsVisible, setTagsVisible] = useState(false);
  const [drawerVisible, setDrawerVisible] = useState(false);
  const [taggedUsersVisible, setTaggedUsersVisible] = useState(false);
  const [hideText, setHideText] = useState(false);

  const [fadeValue, setFadeValue] = useState<Animated.Value<number>>(
    new Animated.Value(0),
  );
  const [commentCount, setCommentCount] = useState<number>(
    moment.comments_count,
  );
  const [aspectRatio, setAspectRatio] = useState<number>(1);
  const [momentTagId, setMomentTagId] = useState<string>('');

  const imageRef = useRef(null);
  const videoRef = useRef<Video>(null);
  const {keyboardVisible, currentVisibleMomentId} = useContext(MomentContext);
  const isVideo = !(
    moment.moment_url.endsWith('jpg') ||
    moment.moment_url.endsWith('JPG') ||
    moment.moment_url.endsWith('PNG') ||
    moment.moment_url.endsWith('png') ||
    moment.moment_url.endsWith('GIF') ||
    moment.moment_url.endsWith('gif')
  );
  const mediaHeight = SCREEN_WIDTH / aspectRatio;
  const [viewCount, setViewCount] = useState<number>(moment.view_count);

  /*
   * Load tags on initial render to pass tags data to moment header and content
   */
  useEffect(() => {
    loadMomentTags(moment.moment_id).then((response) => {
      setTags(response ? response : []);
    });
  }, [moment]);

  /*
   * Check if loggedInUser has been tagged in the picture and set the id
   */
  useEffect(() => {
    const getMomentTagId = () => {
      const ownTag: MomentTagType[] = tags.filter(
        (tag) => tag.user.id === loggedInUserId,
      );
      if (ownTag?.length > 0) {
        setMomentTagId(ownTag[0].id);
      } else {
        setMomentTagId('');
      }
    };
    getMomentTagId();
  }, [tags]);

  /*
   * Remove tag and update the current tags
   */
  const removeTag = async () => {
    const success = await deleteMomentTag(momentTagId);
    if (success) {
      const filteredTags = tags.filter((tag) => tag.user.id !== loggedInUserId);
      setTags(filteredTags);
    }
  };

  useEffect(
    () =>
      navigation.setOptions({
        ...headerBarOptions('white', ''),
        headerTitle: () => (
          <IndividualMomentTitleBar title={moment.moment_category} />
        ),
      }),
    [moment.moment_id],
  );

  /*
   *  Determines if an image is 9:16 to set aspect ratio of current image and
   * determine if image must be displayed in full screen or not
   */
  useEffect(() => {
    if (!isVideo) {
      Image.getSize(
        moment.moment_url,
        (w, h) => {
          setAspectRatio(w / h);
        },
        (err) => console.log(err),
      );
    }
  }, []);

  /*
   * To animate tags display
   */
  useEffect(() => {
    const fade = async () => {
      Animated.timing(fadeValue, {
        toValue: 1,
        duration: 250,
        easing: EasingNode.linear,
      }).start();
    };
    fade();
  }, [fadeValue]);

  useEffect(() => {
    if (!keyboardVisible && hideText) {
      setHideText(false);
    }
  }, [keyboardVisible, hideText]);

  useEffect(() => {
    if (moment.moment_id !== currentVisibleMomentId) {
      videoRef.current?.seek(0);
    }
  }, [currentVisibleMomentId]);

  const momentPosterPreview = useMemo(
    () => (
      <View style={styles.momentPosterContainer}>
        <TouchableOpacity
          onPress={() =>
            navigateToProfile(state, dispatch, navigation, screenType, user)
          }
          style={styles.header}>
          <TaggAvatar
            style={styles.avatar}
            userXId={userXId}
            screenType={screenType}
            editable={false}
          />
          <View style={styles.profilePreviewContainer}>
            <Text style={styles.headerText}>{user.username}</Text>
            <Text style={styles.viewCount}>
              {moment.view_count <= 9999
                ? `${moment.view_count} Views`
                : `${(moment.view_count / 1000).toFixed(1)}K Views`}
            </Text>
          </View>
        </TouchableOpacity>
      </View>
    ),
    [user.username, moment.view_count],
  );

  const momentMedia = isVideo ? (
    <View ref={imageRef}>
      <Video
        ref={videoRef}
        source={{
          uri: moment.moment_url,
        }}
        volume={1}
        style={{
          height: mediaHeight,
        }}
        repeat={true}
        onLoad={(response) => {
          const {width, height} = response.naturalSize;
          setAspectRatio(width / height);
        }}
        paused={moment.moment_id !== currentVisibleMomentId}
        onEnd={updateMomentViewCount}
      />
    </View>
  ) : (
    <Image
      source={{uri: moment.moment_url}}
      style={{
        height: mediaHeight,
      }}
      ref={imageRef}
    />
  );

  return (
    <>
      <StatusBar barStyle={'light-content'} />
      <TaggedUsersDrawer
        users={tags.map((tag) => tag.user)}
        isOpen={taggedUsersVisible}
        setIsOpen={setTaggedUsersVisible}
      />
      <SafeAreaView style={styles.moreInfoButton}>
        <MomentMoreInfoDrawer
          isOpen={drawerVisible}
          setIsOpen={setDrawerVisible}
          isOwnProfile={isOwnProfile}
          momentTagId={momentTagId}
          removeTag={removeTag}
          dismissScreenAndUpdate={() => {
            dispatch(loadUserMoments(loggedInUserId));
            navigation.goBack();
          }}
          screenType={screenType}
          moment={moment}
          tags={tags}
        />
      </SafeAreaView>
      <View style={styles.background}>
        <TouchableWithoutFeedback
          onPress={() => {
            if (keyboardVisible) {
              Keyboard.dismiss();
            } else {
              setTagsVisible(!tagsVisible);
              setFadeValue(new Animated.Value(0));
            }
          }}>
          {isVideo ? (
            <View style={styles.mediaContainer}>{momentMedia}</View>
          ) : (
            <Pinchable>
              <View style={styles.mediaContainer}>{momentMedia}</View>
              {tagsVisible && !isVideo && (
                <Animated.View
                  style={[styles.tagsContainer, {opacity: fadeValue}]}>
                  <MomentTags
                    editing={false}
                    tags={tags}
                    setTags={() => null}
                    imageRef={imageRef}
                  />
                </Animated.View>
              )}
            </Pinchable>
          )}
        </TouchableWithoutFeedback>
        <View style={styles.bottomContainer} pointerEvents={'box-none'}>
          <KeyboardAvoidingView
            behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
            keyboardVerticalOffset={-20}>
            {tags.length > 0 && !keyboardVisible && (
              <TouchableOpacity
                style={styles.tagIconContainer}
                disabled={!isVideo}
                onPress={() =>
                  setTaggedUsersVisible((prevState) => !prevState)
                }>
                <Image
                  source={require('../../assets/icons/tag_indicate.png')}
                  style={styles.tagIcon}
                />
              </TouchableOpacity>
            )}
            <View style={styles.commentsCountContainer}>
              <CommentsCount
                momentId={moment.moment_id}
                count={commentCount}
                screenType={screenType}
              />
            </View>
            {momentPosterPreview}
            {!hideText &&
              moment.caption !== '' &&
              renderTextWithMentions({
                value: moment.caption,
                styles: styles.captionText,
                partTypes: mentionPartTypes('white', 'caption'),
                onPress: (userLocal: UserType) =>
                  navigateToProfile(
                    state,
                    dispatch,
                    navigation,
                    screenType,
                    userLocal,
                  ),
              })}
            <AddComment
              placeholderText={'Add a comment here!'}
              momentId={moment.moment_id}
              callback={() => {
                setCommentCount(commentCount + 1);
              }}
              onFocus={() => {
                setHideText(true);
              }}
              isKeyboardAvoiding={false}
              theme={'dark'}
            />
            <Text style={styles.text}>
              {getTimePosted(moment.date_created)}
            </Text>
          </KeyboardAvoidingView>
        </View>
      </View>
    </>
  );
};

const styles = StyleSheet.create({
  mediaContainer: {
    height: SCREEN_HEIGHT,
    width: SCREEN_WIDTH,
    justifyContent: 'center',
  },
  text: {
    marginHorizontal: '5%',
    color: 'white',
    fontWeight: '500',
    textAlign: 'right',
    marginTop: 5,
  },
  captionText: {
    position: 'relative',
    marginHorizontal: '5%',
    color: '#ffffff',
    fontWeight: '500',
    fontSize: normalize(13),
    lineHeight: normalize(15.51),
    letterSpacing: normalize(0.6),
    marginBottom: normalize(5),
    width: SCREEN_WIDTH * 0.79,
  },
  tagIconContainer: {
    width: normalize(30),
    height: normalize(30),
    bottom: normalize(20),
    left: '5%',
  },
  tagIcon: {
    width: '100%',
    height: '100%',
  },
  avatar: {
    width: 48,
    aspectRatio: 1,
    borderRadius: 100,
    marginLeft: '3%',
  },
  headerText: {
    fontSize: 15,
    fontWeight: 'bold',
    color: 'white',
  },
  viewCount: {
    height: normalize(12),
    left: 0,
    top: '8%',
    fontSize: 11,
    fontWeight: '600',
    lineHeight: 13,
    letterSpacing: 0.08,
    textAlign: 'left',
    color: '#fff',
  },
  header: {
    alignItems: 'center',
    flexDirection: 'row',
    marginBottom: normalize(15),
    alignSelf: 'flex-start',
  },
  momentPosterContainer: {
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  commentsCountContainer: {
    position: 'absolute',
    zIndex: 3,
    right: '2%',
    bottom: SCREEN_HEIGHT * 0.12,
  },
  moreInfoButton: {
    position: 'absolute',
    zIndex: 999,
    top: 5,
    right: 25,
  },
  bottomContainer: {
    position: 'absolute',
    width: SCREEN_WIDTH,
    height: SCREEN_HEIGHT,
    flexDirection: 'column',
    justifyContent: 'flex-end',
    paddingBottom: '24%',
  },
  tagsContainer: {
    position: 'absolute',
    width: SCREEN_WIDTH,
    height: SCREEN_HEIGHT,
  },
  background: {
    backgroundColor: 'black',
    width: SCREEN_WIDTH,
    height: SCREEN_HEIGHT,
  },
  profilePreviewContainer: {paddingHorizontal: '3%'},
});

export default MomentPost;
