import React, { useCallback, useEffect, useState } from 'react';
import { Keyboard, StyleSheet } from 'react-native';
import { FAB, Snackbar } from 'react-native-paper';
import { ParamListBase, useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { pick } from 'react-native-document-picker';
import { useDeviceOrientation } from '@react-native-community/hooks';
import Clipboard from '@react-native-clipboard/clipboard';
import { documentPickerResponseToAddMemeFile, ROUTE } from '../types';
import {
  allowedMimeTypes,
  getFilenameFromUri,
  guessMimeType,
  noOp,
} from '../utilities';

const floatingActionButtonStyles = StyleSheet.create({
  fab: {
    paddingBottom: 90,
    paddingRight: 10,
  },
  fabLandscape: {
    paddingBottom: 40,
    paddingRight: 12,
  },
  snackbar: {
    marginBottom: 90,
  },
});

const FloatingActionButton = ({ visible = true }: { visible?: boolean }) => {
  const { navigate } =
    useNavigation<NativeStackNavigationProp<ParamListBase>>();
  const orientation = useDeviceOrientation();

  const [state, setState] = useState(false);
  const [keyboardOpen, setKeyboardOpen] = useState(false);

  const [snackbarMessage, setSnackbarMessage] = useState<string>();

  useEffect(() => {
    const keyboardDidShowListener = Keyboard.addListener(
      'keyboardDidShow',
      () => setKeyboardOpen(true),
    );
    const keyboardDidHideListener = Keyboard.addListener(
      'keyboardDidHide',
      () => setKeyboardOpen(false),
    );

    return () => {
      keyboardDidShowListener.remove();
      keyboardDidHideListener.remove();
    };
  }, []);

  const handleAddMeme = useCallback(async () => {
    const response = await pick({
      type: allowedMimeTypes,
      allowMultiSelection: true,
    }).catch(noOp);
    if (!response) return;
    const files = documentPickerResponseToAddMemeFile(response);
    navigate(ROUTE.ADD_MEME, { files });
  }, [navigate]);

  const handleAddTag = useCallback(() => {
    navigate(ROUTE.ADD_TAG);
  }, [navigate]);

  const handlePaste = useCallback(async () => {
    const uri = await Clipboard.getURI();
    if (!uri) {
      setSnackbarMessage('Clipboard does not contain a URI.');
      return;
    }
    const mimeType = guessMimeType(uri);
    if (!mimeType) {
      setSnackbarMessage('Unsupported MIME type.');
      return;
    }
    navigate(ROUTE.ADD_MEME, {
      files: [
        {
          uri: uri,
          filename: getFilenameFromUri(uri),
          type: mimeType,
        },
      ],
    });
  }, [navigate]);

  return (
    <>
      <FAB.Group
        open={state}
        visible={visible && !keyboardOpen}
        icon={state ? 'close' : 'plus'}
        actions={[
          {
            icon: 'content-paste',
            label: 'Paste',
            onPress: handlePaste,
          },
          {
            icon: 'tag',
            label: 'Tag',
            onPress: handleAddTag,
          },
          {
            icon: 'image',
            label: 'Meme',
            onPress: handleAddMeme,
          },
        ]}
        onStateChange={({ open }) => setState(open)}
        style={
          orientation === 'portrait'
            ? floatingActionButtonStyles.fab
            : floatingActionButtonStyles.fabLandscape
        }
      />
      <Snackbar
        visible={!!snackbarMessage}
        // eslint-disable-next-line unicorn/no-useless-undefined
        onDismiss={() => setSnackbarMessage(undefined)}
        style={floatingActionButtonStyles.snackbar}
        action={{
          label: 'Dismiss',
          // eslint-disable-next-line unicorn/no-useless-undefined
          onPress: () => setSnackbarMessage(undefined),
        }}>
        {snackbarMessage}
      </Snackbar>
    </>
  );
};

export default FloatingActionButton;
