import { RainbowContext } from '../../store';
import React, { useEffect, useState } from 'react';
import { Alert, SectionList, SectionListData, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Strings } from '../../resources/localization/Strings'
import { IContact } from '../../store/contacts/types';
import { eventEmitter, EventType } from '../../services/EventEmitter';
import {
  giveOwnerShip,
  hangupParticipant,
  promoteBubbleParticipant,
  demoteBubbleParticipant,
  removeContactFromBubble
} from '../../store/bubbles/bubblesSlice';
import { IBubble, IBubbleParticipant } from '../../store/bubbles/types';
import { ContactCardView } from '../contacts/ContactCardView';
import { checkIfAllUserAreMutedResult, muteAllParticipants, unMuteAllParticipants } from '../../store/conference/conferenceSlice';
import { Logger } from '../../utils/Log';
import { IConference, IConferenceParticipants } from '../../store/conference/types';
import { DropDownMenu } from '../common/DropDownMenu';
import Icon from 'react-native-vector-icons/FontAwesome5';
import { useAppDispatch, useAppSelector } from '../../store/hooks';

const logger = new Logger('BubbleParticipantsList');
interface IProps {
  bubble: IBubble;
  conferenceCall?: IConference;
}

export const BubbleParticipants: React.FunctionComponent<IProps> = ({
  bubble,
  conferenceCall,
}) => {

  const [conferenceAttendees, setConferenceAttendees] = useState<IConferenceParticipants[]>(conferenceCall?.attendees ?? []);
  const { bubbleOwner, isMyUserOwner, isMyUserModerator, hasActiveConference, participants } = bubble;
  const dispatch = useAppDispatch();
  const areAllConfUsersMuted = useAppSelector((state) => state.conference.areAllConfUsersMuted);


  useEffect(() => {
    const areAllConfUserMutedEvent = eventEmitter.addListener(EventType.AreAllConfUserMuted, (areAllConfUserMuted: boolean) => {
      logger.info(`AreAllConfUserMuted:  ${areAllConfUserMuted}`);
      dispatch(checkIfAllUserAreMutedResult(areAllConfUserMuted));
    });

    const conferenceAttendeesUpdatesEvent = eventEmitter.addListener(EventType.ConferenceAttendeesUpdates, (attendees: IConferenceParticipants[]) => {
      logger.info(`get conference participants with count ${attendees?.length}`);
      setConferenceAttendees(attendees);
    });

    //TODO: handle it as participant update
    // TODO: handle the failure case
    const removeContactFromBubbleResultEvent = eventEmitter.addListener(EventType.RemoveContactFromBubbleResult, (eventData: { members: IContact[], organizers: IContact[] }) => {
      logger.info(`addListener for ${EventType.RemoveContactFromBubbleResult} : ${eventData}`)
      // setBubbleMembersResult(eventData.members);
      // setOrganizers(eventData.organizers);
    });

    const promoteBubbleOwnerResultEvent = eventEmitter.addListener(EventType.PromoteBubbleOwnerResult, (eventData: string) => {
      logger.info(`addListener for ${EventType.PromoteBubbleOwnerResult} : ${eventData}`);
      if (eventData === 'failure') {
        Alert.alert('Failure', 'Failed with promote the user to bubble owner');
      }
    });

    const hangUpParticipantFailedEvent = eventEmitter.addListener(EventType.HangUpParticipantFailed, (eventData: string) => {
      logger.info(`addListener for ${EventType.HangUpParticipantFailed} : ${eventData}`)
      Alert.alert('Failure', eventData)
    });


    return () => {
      areAllConfUserMutedEvent.remove();
      conferenceAttendeesUpdatesEvent.remove();
      removeContactFromBubbleResultEvent.remove();
      promoteBubbleOwnerResultEvent.remove();
      hangUpParticipantFailedEvent.remove();
    }
  }, [bubble, conferenceCall, areAllConfUsersMuted]);

  const onHangupParticipant = (bubbleId: string, participantJid: string) => {
    dispatch(hangupParticipant({bubbleId, contactJid: participantJid}))
  }

  enum BubbleParticipantOption {
    RemoveContact = 'Remove Contact',
    GiveOwnerShip = 'Give OwnerShip',
    HangupParticipant = 'Hang-Up participant',
    PromoteContact = 'Promote Contact',
    DemoteContact = 'Demote Contact'
  }



  const renderDropDown = (contact: IContact) => {
    const contactParticipant = contact as IBubbleParticipant;
    const { isMyUser } = contactParticipant;
    const contactJid = contactParticipant.jId;
    const ownerJId = bubbleOwner.jId;
    const options: BubbleParticipantOption[] = [];

    const isThisContactBubbleOwner = contactJid === ownerJId;
    const isUserOrganizer = contactParticipant.isModerator;
    const isMyUserAttendees = conferenceCall?.hasMyUserJoinedConferenceCall;
    const isParticipantConferenceIsOwner = conferenceCall?.isOwner;
    const canRemoveParticipant = isMyUserModerator && !isMyUser && !isThisContactBubbleOwner && !isMyUserAttendees;
    const canHangUpParticipant = isMyUserAttendees && isMyUserModerator && !isParticipantConferenceIsOwner && !isMyUser;
    const canGiveOwnerShipToParticipant = isMyUserOwner && isUserOrganizer && !isThisContactBubbleOwner && !isMyUser && !hasActiveConference;
    const canPromoteMember = !isMyUser && !isThisContactBubbleOwner && !isUserOrganizer && isMyUserModerator;
    const canDemoteOrganizer = !isMyUser && !isThisContactBubbleOwner && isUserOrganizer && isMyUserModerator;

    const handleOnParticipantMenuClicked = (item: string) => {
      switch (item) {
        case BubbleParticipantOption.RemoveContact:
          dispatch(removeContactFromBubble({bubbleId: bubble.id, contactJid}))
          break;
        case BubbleParticipantOption.GiveOwnerShip:
          dispatch(giveOwnerShip({bubbleId: bubble.id, contactJid}))
          break;
        case BubbleParticipantOption.HangupParticipant:
        onHangupParticipant(bubble.id, contactJid);
          break;
        case BubbleParticipantOption.PromoteContact:
          dispatch(promoteBubbleParticipant({bubbleId: bubble.id, contactJid}))
          break;
        case BubbleParticipantOption.DemoteContact:
          dispatch(demoteBubbleParticipant({bubbleId: bubble.id, contactJid}))
          break;
      }
    }

    if (canRemoveParticipant) {
      options.push(BubbleParticipantOption.RemoveContact);
    }
    if (canGiveOwnerShipToParticipant) {
      options.push(BubbleParticipantOption.GiveOwnerShip);
    }
    if (canHangUpParticipant) {
      options.push(BubbleParticipantOption.HangupParticipant);
    }
    if (canPromoteMember) {
      options.push(BubbleParticipantOption.PromoteContact);
    }
    if (canDemoteOrganizer) {
      options.push(BubbleParticipantOption.DemoteContact);
    }
    if (options.length > 0) {
      return <DropDownMenu menuItems={options} style={{ menuIcon: styles.menuIcon }} onSelectItem={handleOnParticipantMenuClicked} />
    }
    if (isThisContactBubbleOwner) {
      return <Icon name="crown" style={styles.ownerIcon} />

    }
    else {
      return null
    }
  };

  const renderItem = ({ item }: { item?: IContact }) => {
    if (item) {
      return (
        <ContactCardView contact={item} rightItem={renderDropDown(item)} />
      );
    }
    return null;
  };

  const renderSectionHeader = ({
    section,
  }: {
    section: SectionListData<IContact>;
  }) => {
    if (section.data.length > 0) {
      return <Text style={styles.sectionHeader}>{section.title}</Text>;
    }
    return null;
  };

  const muteUnmuteParticipants = (bubbleId: string) => () => {
    if (areAllConfUsersMuted)
    dispatch(unMuteAllParticipants(bubbleId));
    else
    dispatch(muteAllParticipants(bubbleId));
  }

  const getSections = () => {
    const bubbleParticipants = participants;
    if (conferenceCall && conferenceCall?.hasMyUserJoinedConferenceCall) {
      const nonAttendees = bubbleParticipants.filter((participant: IBubbleParticipant) => !conferenceAttendees.some((attendee: IConferenceParticipants) => participant.jId === attendee.jId));
      return [
        {
          title: `${Strings.Attendees} (${conferenceAttendees.length})`,
          data: conferenceAttendees as IContact[]
        },
        {
          title: `${Strings.NonAttendees} (${nonAttendees.length})`,
          data: nonAttendees as IContact[]
        }
      ]
    }
    else {
      const organizers = bubbleParticipants.filter((participant: IBubbleParticipant) => participant.isModerator);
      const members = bubbleParticipants.filter((participant: IBubbleParticipant) => !participant.isModerator);
      return [
        {
          title: Strings.Organizer,
          data: organizers as IContact[]
        },
        {
          title: Strings.Members,
          data: members as IContact[]
        }
      ]
    }

  }

  const renderSectionList = () => {
    return (
      <SectionList
        sections={getSections()}
        stickySectionHeadersEnabled={true}
        renderItem={renderItem}
        maxToRenderPerBatch={20}
        windowSize={10}
        renderSectionHeader={renderSectionHeader}
        extraData={bubbleOwner}
      />
    )
  }

  return (
    <View style={styles.container}>
      {renderSectionList()}
      {(conferenceCall?.hasMyUserJoinedConferenceCall && isMyUserModerator) && (
        <TouchableOpacity style={styles.muteAllButtonContainer} onPress={muteUnmuteParticipants(bubble.id)}>
          <View style={styles.muteAllButtonView}>
            {areAllConfUsersMuted ?
              <Icon name="microphone-slash" style={styles.micIcon} /> :
              <Icon name="microphone" style={styles.micIcon} />
            }
          </View>
        </TouchableOpacity>
      )
      }
    </View>

  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 10,
  },
  sectionHeader: {
    paddingTop: 5,
    paddingBottom: 5,
    paddingLeft: 10,
    paddingRight: 10,
    fontSize: 15,
    fontWeight: 'bold',
    color: '#0086CF',
    backgroundColor: '#eeeded',
  },
  ownerIcon: { color: '#0086CF', fontSize: 20 },
  muteAllButtonContainer: { position: 'absolute', bottom: 10, width: '100%' },
  muteAllButtonView: { backgroundColor: '#02a2ff', alignItems: 'center' },
  micIcon: { color: 'white' },
  menuIcon: { color: '#0086CF', fontSize: 30 }
});
