import {
  Avatar,
  AvatarGroup,
  Box,
  Button,
  CircularProgress,
  Container,
  Dialog,
  Divider,
  FormControl,
  FormHelperText,
  IconButton,
  InputLabel,
  MenuItem,
  Select,
  Stack,
  Switch,
  Tooltip,
  Typography,
} from '@mui/material';
import {
  FiChevronsLeft,
  FiChevronsRight,
  FiCircle,
  FiRss,
  FiSettings,
  FiSun,
  FiVideo,
  FiVideoOff,
  FiX,
  FiZap,
  FiZapOff,
} from 'react-icons/fi';
import { MasterConversation, RoomMap } from '../util/types';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { ConversationUserMember } from '@nirvana/core/models/conversation.model';
import { SUPPORT_DISPLAY_NAME } from '../util/support';
import { blueGrey } from '@mui/material/colors';
import useAuth from '../providers/AuthProvider';
import useConversations from '../providers/ConversationProvider';
import useDevices from '../hooks/useDevices';
import useElectron from '../providers/ElectronProvider';
import useSearch from '../providers/SearchProvider';
import useZen from '../providers/ZenProvider';

export default function FooterControls() {
  const { handleFlowState } = useZen();

  const { selectedConversation, priorityConversations, userLocalStream, handleToggleVideo } =
    useConversations();
  const { user, handleLogout } = useAuth();

  const { handleToggleDesktopMode, desktopMode } = useElectron();

  const [openUserSettings, setOpenUserSettings] = useState<boolean>(false);

  const handleTurnOnFlowState = useCallback(() => {
    // when in overlay mode, we need to toggle main app and then go into flow state

    if (desktopMode === 'overlayOnly') {
      handleToggleDesktopMode();
    }

    handleFlowState();
  }, [handleFlowState, desktopMode, handleToggleDesktopMode]);

  const handleClickProfile = useCallback(
    (event: React.MouseEvent<HTMLElement>) => {
      if (desktopMode === 'overlayOnly') {
        handleToggleDesktopMode();
      }

      setOpenUserSettings(true);
    },
    [setOpenUserSettings, handleToggleDesktopMode, desktopMode],
  );

  const handleCloseUserSettings = useCallback(() => {
    setOpenUserSettings(false);
  }, [setOpenUserSettings]);

  // is there a selected conversation and if so, is it a priority one?
  const isSelectedConversationPriority = useMemo(() => {
    const priorityIds =
      priorityConversations.map((priorityConvo) => priorityConvo._id.toString()) ?? [];

    if (selectedConversation && priorityIds.includes(selectedConversation._id.toString())) {
      return true;
    }

    return false;
  }, [selectedConversation, priorityConversations]);

  const localVideoRef = useRef<HTMLVideoElement>(null);
  useEffect(() => {
    if (localVideoRef?.current && userLocalStream) {
      localVideoRef.current.srcObject = userLocalStream;
    }
  }, [localVideoRef, userLocalStream]);

  return (
    <Box
      sx={{
        maxWidth: 80,
        width: '100%',
        zIndex: 10,
        boxShadow: 10,

        bgcolor: blueGrey[800],

        display: 'flex',
        flexDirection: 'column',
      }}
      className={'titlebar'}
    >
      <Stack
        direction={'column'}
        alignItems={'center'}
        justifyContent={'flex-start'}
        sx={{
          p: 1,
          flex: 1,
          overflow: 'auto',
        }}
      >
        {priorityConversations.map((masterPriorityConversation) => (
          <OverlayConversation
            key={`priorityConversationOverlay-${masterPriorityConversation._id.toString()}`}
            masterConversation={masterPriorityConversation}
            isSelected={
              masterPriorityConversation._id.toString() === selectedConversation?._id.toString()
            }
          />
        ))}

        {selectedConversation && !isSelectedConversationPriority && (
          <>
            <Divider orientation="horizontal" flexItem />
            <OverlayConversation masterConversation={selectedConversation} isSelected={true} />
          </>
        )}
      </Stack>

      <Stack sx={{ mt: 'auto' }} spacing={1} direction={'column'} alignItems={'center'}>
        <Divider orientation="horizontal" flexItem />

        <Tooltip title="Show video!">
          <IconButton size={'small'} sx={{ color: 'white' }} onClick={handleToggleVideo}>
            {userLocalStream ? <FiVideo /> : <FiVideoOff />}
          </IconButton>
        </Tooltip>

        <Divider orientation="horizontal" flexItem />

        <Button size={'small'} color={'secondary'} variant="text" onClick={handleTurnOnFlowState}>
          flow
        </Button>

        <IconButton
          onClick={handleClickProfile}
          size="small"
          sx={{ borderRadius: 1 }}
          aria-controls={open ? 'account-menu' : undefined}
          aria-haspopup="true"
          aria-expanded={open ? 'true' : undefined}
        >
          {userLocalStream ? (
            <Box height={40} width={40} ref={localVideoRef} component={'video'} autoPlay muted />
          ) : (
            <Avatar alt={user.givenName} src={user.picture} />
          )}
        </IconButton>

        <Divider orientation="horizontal" flexItem />

        <Tooltip title={desktopMode === 'overlayOnly' ? 'expand' : 'collapse'}>
          <IconButton color={'info'} onClick={handleToggleDesktopMode}>
            {desktopMode === 'overlayOnly' ? <FiChevronsLeft /> : <FiChevronsRight />}
          </IconButton>
        </Tooltip>
      </Stack>

      <UserSettingsDialog open={openUserSettings} handleClose={handleCloseUserSettings} />
    </Box>
  );
}

function OverlayConversation({
  masterConversation,
  isSelected = false,
}: {
  masterConversation: MasterConversation;
  isSelected?: boolean;
}) {
  const { user } = useAuth();

  const { selectConversation, handleEscape, updateConversationPriority, userLocalStream } =
    useConversations();

  const handleSelectConversation = useCallback(() => {
    if (!isSelected) {
      selectConversation(masterConversation._id.toString(), false);
    }
  }, [masterConversation, selectConversation, isSelected]);

  const isPriority = useMemo(() => {
    const personalConvoMember = masterConversation.members.find(
      (mem) => mem._id.toString() === user._id.toString(),
    );
    if (personalConvoMember && personalConvoMember.memberState === 'priority') {
      return true;
    }

    return false;
  }, [masterConversation, user]);

  const handleToggleConversationZap = useCallback(() => {
    if (isPriority) {
      updateConversationPriority(masterConversation._id.toString(), 'inbox');
      return;
    }
    updateConversationPriority(masterConversation._id.toString(), 'priority');
  }, [updateConversationPriority, isPriority, masterConversation._id]);

  const userVideoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    //
  }, []);

  return (
    <Stack
      direction={'column'}
      spacing={1}
      sx={{
        mb: 1,
        p: 1,
        borderRadius: 2,
        bgcolor: isSelected ? blueGrey[300] : blueGrey[600],
        transition: (theme) =>
          theme.transitions.create(['background-color', 'transform'], {
            duration: theme.transitions.duration.standard,
          }),

        cursor: 'pointer',

        '&:hover': {
          bgcolor: blueGrey[300],
        },
      }}
      onClick={handleSelectConversation}
      alignItems={'center'}
    >
      {/*  status */}
      <Box
        component={'span'}
        sx={{
          bgcolor: (theme) => theme.palette.secondary.main,
          height: 5,
          width: 5,
          borderRadius: 100,
        }}
      />

      <OverlayConversationAvatars
        conversationUserMembers={masterConversation.members}
        isConversationSelected={isSelected}
        tunedInUserIds={masterConversation.tunedInUsers}
        roomPeers={masterConversation.room}
        localStreamToPeers={masterConversation.localStream}
      />

      {isSelected && (
        <>
          <Divider orientation="horizontal" flexItem />

          <Tooltip title={'enter to toggle, ~ to push to talk'}>
            <IconButton color={'primary'} size="small">
              {isPriority ? <FiSun /> : <FiCircle />}
            </IconButton>
          </Tooltip>

          <Divider orientation="horizontal" flexItem />

          <Tooltip title={isPriority ? 'zapped' : 'un-zapped'}>
            <IconButton
              sx={{
                color: 'white',
                fontSize: 15,
              }}
              aria-selected={isPriority ? true : false}
              onClick={handleToggleConversationZap}
            >
              {isPriority ? <FiZap /> : <FiZapOff />}
            </IconButton>
          </Tooltip>

          <Tooltip title="hit escape!">
            <IconButton
              sx={{
                color: 'GrayText',
              }}
              size="small"
              onClick={handleEscape}
            >
              <FiX />
            </IconButton>
          </Tooltip>
        </>
      )}
    </Stack>
  );
}

function OverlayConversationAvatars({
  conversationUserMembers,
  tunedInUserIds,
  isConversationSelected,
  roomPeers,
  localStreamToPeers,
}: {
  isConversationSelected: boolean;
  tunedInUserIds: string[];
  conversationUserMembers: ConversationUserMember[];
  roomPeers: RoomMap;
  localStreamToPeers: MediaStream;
}) {
  const { user } = useAuth();

  const sortedMembers = useMemo(() => {
    const sortedUserMembers = [...conversationUserMembers];
    sortedUserMembers.sort((convoUserA, convoUserB) => {
      if (convoUserA._id.toString() === user?._id.toString()) return 2;

      if (tunedInUserIds?.includes(convoUserA._id.toString())) return 1;

      if (tunedInUserIds?.includes(convoUserB._id.toString())) return -1;

      return -2;
    });

    return sortedUserMembers;
  }, [conversationUserMembers, user, tunedInUserIds]);

  console.log(roomPeers);

  return (
    <AvatarGroup
      variant={'rounded'}
      sx={{
        display: 'flex',
        flexDirection: 'column',
        '& >:first-child': {
          marginTop: 0,
        },
        '& > *': {
          marginLeft: '0 !important' as any,
          marginTop: -2,
        },
      }}
      max={3}
    >
      {sortedMembers?.map((conversationUserMember, index) => (
        <OverlayConversationAvatar
          key={`${conversationUserMember._id.toString()}-overlayConvoAvatar`}
          isTunedIn={tunedInUserIds?.includes(conversationUserMember._id.toString())}
          isConversationSelected={isConversationSelected}
          conversationUserMember={conversationUserMember}
          isConnecting={
            (roomPeers && roomPeers[conversationUserMember._id.toString()]?.isConnecting) ?? false
          }
          localStreamToPeers={localStreamToPeers}
        />
      ))}
    </AvatarGroup>
  );
}

function OverlayConversationAvatar({
  conversationUserMember,
  isTunedIn,
  isConversationSelected,
  isConnecting,
  localStreamToPeers,
}: {
  conversationUserMember: ConversationUserMember;
  isTunedIn: boolean;
  isConversationSelected: boolean; // if user is connecting or just have this conversation selected
  isConnecting: boolean; // if we are calling or receiving call from this person and still connecting
  localStreamToPeers: MediaStream; // the local stream that is casted to each peer
}) {
  const { user } = useAuth();

  const localVideoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    if (localVideoRef?.current && localStreamToPeers) {
      localVideoRef.current.srcObject = localStreamToPeers;
    }
  }, [localVideoRef, localStreamToPeers]);

  console.log(isConnecting);

  if (isConnecting) {
    return <CircularProgress />;
  }

  if (conversationUserMember._id.toString() === user._id.toString() && localStreamToPeers) {
    return (
      <Box
        height={40}
        width={40}
        ref={localVideoRef}
        component={'video'}
        autoPlay
        muted
        border={'2px solid #fff'}
      />
    );
  }

  return (
    <Avatar
      alt={conversationUserMember?.givenName}
      src={conversationUserMember?.picture}
      sx={{
        opacity: isTunedIn ? '100%' : '20%',
      }}
    />
  );
  return <></>;
}

const NO_DEVICE_SELECTION = 'NA';

function UserSettingsDialog({ open, handleClose }: { handleClose: () => void; open: boolean }) {
  const { user, handleLogout } = useAuth();
  const devices = useDevices();

  const { omniSearch } = useSearch();
  const handleQuickDialSupport = useCallback(() => {
    omniSearch(SUPPORT_DISPLAY_NAME);
    handleClose();
  }, [omniSearch, handleClose]);

  return (
    <Dialog maxWidth={'sm'} open={open} fullWidth onClose={handleClose}>
      <Container
        maxWidth={false}
        sx={{
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
          alignItems: 'center',
          gap: 2,
          flex: 1,
          background: blueGrey[50],
          position: 'relative',
        }}
      >
        <IconButton sx={{ position: 'absolute', top: 10, right: 10 }} onClick={handleClose}>
          <FiX />
        </IconButton>

        <Container
          maxWidth="sm"
          sx={{
            display: 'flex',
            flexDirection: 'column',
            p: 10,
            gap: 2,
          }}
        >
          <Stack flexDirection={'row'} justifyContent={'space-between'}>
            <Typography variant="h6">Media Settings</Typography>

            <Button variant={'text'} color={'secondary'}>
              Unplug everything
            </Button>
          </Stack>

          <Stack direction="row" alignItems="flex-start" spacing={1}>
            <FormControl fullWidth>
              <InputLabel>Microphone</InputLabel>
              <Select label="Microphone">
                <MenuItem value={NO_DEVICE_SELECTION}>
                  <em>None</em>
                </MenuItem>
                {devices.audioInputDevices.map((deviceInfo) => (
                  <MenuItem
                    key={`micDeviceSelection-${deviceInfo.deviceId}`}
                    value={deviceInfo.deviceId}
                  >
                    {deviceInfo.label}
                  </MenuItem>
                ))}
              </Select>
              <FormHelperText>
                Please select distinct speaker and microphone to avoid distortion when you have a
                bluetooth device connected.
              </FormHelperText>
            </FormControl>

            <FormControl fullWidth>
              <InputLabel>Video</InputLabel>
              <Select label="Audio">
                <MenuItem value={NO_DEVICE_SELECTION}>
                  <em>None</em>
                </MenuItem>
                {devices.videoDevices.map((deviceInfo) => (
                  <MenuItem
                    key={`videoDeviceSelection-${deviceInfo.deviceId}`}
                    value={deviceInfo.deviceId}
                  >
                    {deviceInfo.label}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Stack>

          <Divider />

          <Stack flexDirection={'row'} justifyContent={'space-between'} alignItems={'center'}>
            <Typography variant="subtitle2">Questions?</Typography>

            <Button variant={'text'}>Resources</Button>
          </Stack>

          <Divider />

          <Stack flexDirection={'row'} justifyContent={'space-between'} alignItems={'center'}>
            <Typography variant="subtitle2">Help, feedback, and more?</Typography>

            <Button variant={'text'} onClick={handleQuickDialSupport}>
              Contact Us
            </Button>
          </Stack>

          <Divider />

          <Stack flexDirection={'row'} justifyContent={'space-between'} alignItems={'center'}>
            <Typography variant="subtitle2">Account</Typography>

            <Button variant={'text'} onClick={handleLogout} color={'error'}>
              log out
            </Button>
          </Stack>
        </Container>
      </Container>
    </Dialog>
  );
}
