import React, { useMemo } from 'react';
import { HelperText, Text, TextInput, useTheme } from 'react-native-paper';
import { Image, LayoutAnimation } from 'react-native';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import Video from 'react-native-video';
import { LoadingView, MemeFail } from '../../../components';
import {
  getFilenameFromUri,
  getMemeTypeFromMimeType,
  validateMemeTitle,
} from '../../../utilities';
import { StagingMeme } from '../../../types';
import { useMemeDimensions } from '../../../hooks';
import { MEME_TYPE } from '../../../database';
import MemeTagSelector from './memeTagSelector/memeTagSelector';

const memeEditorStyles = {
  media: {
    marginBottom: 15,
    borderRadius: 5,
  },
  uri: {
    marginBottom: 15,
    marginHorizontal: 5,
  },
  memeTagSelector: {
    marginBottom: 10,
  },
  description: {
    marginBottom: 10,
  },
};

const MemeEditor = ({
  uri,
  mimeType,
  loading,
  setLoading,
  error,
  setError,
  staging,
  setStaging,
}: {
  uri?: string;
  mimeType?: string;
  loading: boolean;
  setLoading: (loading: boolean) => void;
  error: Error | undefined;
  setError: (error: Error | undefined) => void;
  staging?: StagingMeme;
  setStaging: (staging: StagingMeme) => void;
}) => {
  const { width } = useSafeAreaFrame();
  const { colors } = useTheme();

  const { dimensions } = useMemeDimensions(
    uri,
    mimeType,
    useMemo(
      () => () => {
        setLoading(false);
        LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
      },
      [setLoading],
    ),
    useMemo(() => (errorIn: Error) => setError(errorIn), [setError]),
  );

  const mediaComponent = useMemo(() => {
    if (!mimeType || !dimensions) return <></>;

    const dimensionStyles = {
      width: width * 0.92,
      height: Math.max(
        Math.min((width * 0.92) / dimensions.aspectRatio, 500),
        100,
      ),
    };

    const memeType = getMemeTypeFromMimeType(mimeType);
    if (!memeType) return <></>;

    switch (memeType) {
      case MEME_TYPE.IMAGE:
      case MEME_TYPE.GIF: {
        return (
          <Image
            source={{ uri }}
            style={[memeEditorStyles.media, dimensionStyles]}
            resizeMode="contain"
          />
        );
      }
      case MEME_TYPE.VIDEO: {
        return (
          <Video
            source={{ uri }}
            style={[memeEditorStyles.media, dimensionStyles]}
            resizeMode="contain"
            controls
          />
        );
      }
      default: {
        return <></>;
      }
    }
  }, [dimensions, mimeType, uri, width]);

  if (!uri || !mimeType || !staging) return <LoadingView />;

  return (
    <>
      <TextInput
        mode="outlined"
        label="Title"
        value={staging.title.raw}
        onChangeText={title =>
          setStaging({ ...staging, title: validateMemeTitle(title) })
        }
        error={!staging.title.valid}
        selectTextOnFocus
      />
      <HelperText type="error" visible={!staging.title.valid}>
        {staging.title.error}
      </HelperText>
      {error ? (
        <MemeFail
          style={[
            {
              width: width * 0.92,
              height: width * 0.92,
            },
            memeEditorStyles.media,
          ]}
          iconSize={50}
        />
      ) : // eslint-disable-next-line unicorn/no-nested-ternary
      loading || !dimensions ? (
        <></>
      ) : (
        mediaComponent
      )}
      <Text
        variant="bodySmall"
        style={[memeEditorStyles.uri, { color: colors.onSurfaceDisabled }]}
        numberOfLines={1}>
        {getFilenameFromUri(uri)}
      </Text>
      <MemeTagSelector
        memeTags={staging.tags}
        setMemeTags={tags => setStaging({ ...staging, tags })}
        style={memeEditorStyles.memeTagSelector}
      />
    </>
  );
};

export default MemeEditor;
