import { Button, Dialog, ModalContext } from '@8base/boost';
import React from 'react';
import { compose } from 'react-apollo';

import {
  ChannelMemberDeleteMutationFn,
  UserChannelsPreviewDocument,
  UserChannelsPreviewQuery,
  UserChannelsPreviewQueryVariables,
  withChannelMemberDelete,
} from 'shared/graphql/__generated__';
import { ChatContext, IChatContext, withContext } from '../../../context';

// -- TYPES

interface ILeaveChannelDialogProps {
  leaveChannel: ChannelMemberDeleteMutationFn;
  channelMembersFilter: IChatContext['channelMembersFilter'];
}

interface IDialogProps extends ILeaveChannelDialogProps {
  channelIdentityId: string;
  onLeave: () => void;
}

// -- CONSTANTS

export const LEAVE_CHANNEL_DIALOG_ID = 'LEAVE_CHANNEL_DIALOG_ID';

// -- MAIN

class DialogContent extends React.Component<IDialogProps> {
  static contextType = ModalContext;

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <Dialog.Header title="Leave channel" onClose={this.closeDialog} />

        <Dialog.Body scrollable={true}>Are you really want to leave?</Dialog.Body>

        <Dialog.Footer>
          <Button color="neutral" variant="outlined" onClick={this.closeDialog}>
            Cancel
          </Button>
          <Button color="danger" type="submit">
            Leave
          </Button>
        </Dialog.Footer>
      </form>
    );
  }

  private onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    const { leaveChannel, channelIdentityId, onLeave, channelMembersFilter } = this.props;

    leaveChannel({
      variables: {
        id: channelIdentityId,
      },
      optimisticResponse: {
        channelMemberDelete: {
          __typename: 'SuccessResponse',
          success: true,
        },
      },
      update: (cache, { data }) => {
        if (!data || !data.channelMemberDelete || !data.channelMemberDelete.success) {
          return;
        }

        let userChannelsPreview;

        try {
          userChannelsPreview = cache.readQuery<
            UserChannelsPreviewQuery,
            UserChannelsPreviewQueryVariables
          >({
            query: UserChannelsPreviewDocument,
            variables: { channelMembersFilter },
          });
          // tslint:disable-next-line: no-empty
        } catch (e) {}

        if (!userChannelsPreview) {
          return;
        }

        cache.writeQuery<UserChannelsPreviewQuery, UserChannelsPreviewQueryVariables>({
          query: UserChannelsPreviewDocument,
          variables: { channelMembersFilter },
          data: {
            ...userChannelsPreview,
            user: {
              ...userChannelsPreview.user,
              channelIdentities: {
                ...userChannelsPreview.user!.channelIdentities,
                items: userChannelsPreview.user!.channelIdentities!.items.filter(
                  el => el.id !== channelIdentityId,
                ),
              },
            },
          },
        });
      },
    });

    onLeave();
    this.closeDialog();
  };

  private closeDialog = () => {
    this.context.closeModal(LEAVE_CHANNEL_DIALOG_ID);
  };
}

function LeaveChannelDialog(props: ILeaveChannelDialogProps) {
  return (
    <Dialog id={LEAVE_CHANNEL_DIALOG_ID} size="sm">
      {({ args }: any) => (
        <DialogContent
          {...props}
          channelIdentityId={args.channelIdentityId}
          onLeave={args.onLeave}
        />
      )}
    </Dialog>
  );
}

LeaveChannelDialog.id = LEAVE_CHANNEL_DIALOG_ID;

export default compose(
  withChannelMemberDelete<{}, ILeaveChannelDialogProps>({
    name: 'leaveChannel',
  }),
  withContext({ context: ChatContext, keys: ['channelMembersFilter'] }),
)(LeaveChannelDialog);
