import React, { useCallback, useContext } from 'react';
import classNames from 'classnames';
import { contextMenu } from 'react-contexify';

import { Avatar, AvatarSize } from '../../avatar/Avatar';

import { createPortal } from 'react-dom';
import {
  openConversationWithMessages,
  ReduxConversationType,
} from '../../../state/ducks/conversations';
import { useDispatch } from 'react-redux';
import { updateUserDetailsModal } from '../../../state/ducks/modalDialog';

import {
  useAvatarPath,
  useConversationUsername,
  useIsPrivate,
} from '../../../hooks/useParamSelector';
import { MemoConversationListItemContextMenu } from '../../menu/ConversationListItemContextMenu';
import { ConversationListItemHeaderItem } from './HeaderItem';
import { MessageItem } from './MessageItem';
import _ from 'lodash';

// tslint:disable-next-line: no-empty-interface
export type ConversationListItemProps = Pick<
  ReduxConversationType,
  'id' | 'isSelected' | 'isBlocked' | 'mentionedUs' | 'unreadCount' | 'displayNameInProfile'
>;

/**
 * This React context is used to share deeply in the tree of the ConversationListItem what is the ID we are currently rendering.
 * This is to avoid passing the prop to all the subtree component
 */
export const ContextConversationId = React.createContext('');

type PropsHousekeeping = {
  style?: Object;
  isMessageRequest?: boolean;
};
// tslint:disable: use-simple-attributes

type Props = ConversationListItemProps & PropsHousekeeping;

const Portal = ({ children }: { children: any }) => {
  return createPortal(children, document.querySelector('.inbox.index') as Element);
};

const AvatarItem = () => {
  const conversationId = useContext(ContextConversationId);
  const userName = useConversationUsername(conversationId);
  const isPrivate = useIsPrivate(conversationId);
  const avatarPath = useAvatarPath(conversationId);
  const dispatch = useDispatch();

  function onPrivateAvatarClick() {
    dispatch(
      updateUserDetailsModal({
        conversationId: conversationId,
        userName: userName || '',
        authorAvatarPath: avatarPath,
      })
    );
  }

  return (
    <div>
      <Avatar
        size={AvatarSize.S}
        pubkey={conversationId}
        onAvatarClick={isPrivate ? onPrivateAvatarClick : undefined}
      />
    </div>
  );
};

// tslint:disable: max-func-body-length
const ConversationListItem = (props: Props) => {
  const {
    unreadCount,
    id: conversationId,
    isSelected,
    isBlocked,
    style,
    mentionedUs,
    isMessageRequest,
  } = props;
  const key = `conversation-item-${conversationId}`;

  const triggerId = `${key}-ctxmenu`;

  const openConvo = useCallback(
    async (e: React.MouseEvent<HTMLDivElement>) => {
      // mousedown is invoked sooner than onClick, but for both right and left click
      if (e.button === 0) {
        await openConversationWithMessages({ conversationKey: conversationId, messageId: null });
      }
    },
    [conversationId]
  );

  return (
    <ContextConversationId.Provider value={conversationId}>
      <div key={key}>
        <div
          role="button"
          onMouseDown={openConvo}
          onMouseUp={e => {
            e.stopPropagation();
            e.preventDefault();
          }}
          onContextMenu={e => {
            contextMenu.show({
              id: triggerId,
              event: e,
            });
          }}
          style={style}
          className={classNames(
            'module-conversation-list-item',
            unreadCount && unreadCount > 0 ? 'module-conversation-list-item--has-unread' : null,
            unreadCount && unreadCount > 0 && mentionedUs
              ? 'module-conversation-list-item--mentioned-us'
              : null,
            isSelected ? 'module-conversation-list-item--is-selected' : null,
            isBlocked ? 'module-conversation-list-item--is-blocked' : null
          )}
        >
          <AvatarItem />
          <div className="module-conversation-list-item__content">
            <ConversationListItemHeaderItem />
            <MessageItem isMessageRequest={Boolean(isMessageRequest)} />
          </div>
        </div>
        <Portal>
          <MemoConversationListItemContextMenu triggerId={triggerId} />
        </Portal>
      </div>
    </ContextConversationId.Provider>
  );
};

export const MemoConversationListItemWithDetails = React.memo(ConversationListItem, _.isEqual);
