/* eslint-disable @typescript-eslint/no-unsafe-return,
                  @typescript-eslint/no-explicit-any,
                  @typescript-eslint/no-unsafe-call,
                  @typescript-eslint/no-unsafe-member-access,
                  @typescript-eslint/no-unsafe-assignment */

import type { ReactNode } from 'react';
import { useState, useCallback } from 'react';

import { FormattedMessage, defineMessages, useIntl } from 'react-intl';

import { Helmet } from 'react-helmet';

import type {
  DragStartEvent,
  DragEndEvent,
  UniqueIdentifier,
  // Announcements,
  // ScreenReaderInstructions,
} from '@dnd-kit/core';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragOverlay,
} from '@dnd-kit/core';
import {
  SortableContext,
  sortableKeyboardCoordinates,
  rectSortingStrategy,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

import MenuIcon from '@/material-icons/400-24px/menu.svg?react';
import EmojiReactionIcon from '@/material-icons/400-24px/mood.svg?react';
import { updateReactionDeck } from 'mastodon/actions/reaction_deck';
import { Button } from 'mastodon/components/button';
import { Column } from 'mastodon/components/column';
import { ColumnHeader } from 'mastodon/components/column_header';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
import { autoPlayGif } from 'mastodon/initial_state';
import { useAppDispatch, useAppSelector } from 'mastodon/store';

import emojify from '../emoji/emoji';

const messages = defineMessages({
  reaction_deck_add: { id: 'reaction_deck.add', defaultMessage: 'Add' },
  heading: { id: 'column.reaction_deck', defaultMessage: 'Reaction deck' },
});

const ReactionEmoji: React.FC<{
  index: number;
  emoji: string;
  emojiMap: any;
  onChange: (index: number, emoji: any) => void;
  onRemove: (index: number) => void;
}> = ({ index, emoji, emojiMap, onChange, onRemove }) => {
  const handleChange = useCallback(
    (emoji: any) => {
      onChange(index, emoji);
    },
    [index, onChange],
  );

  const handleRemove = useCallback(() => {
    onRemove(index);
  }, [index, onRemove]);

  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: index.toString() });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };

  let content: ReactNode;
  const mapEmoji = emojiMap.find((e: any) => e.get('shortcode') === emoji);

  if (mapEmoji) {
    const filename = autoPlayGif
      ? mapEmoji.get('url')
      : mapEmoji.get('static_url');
    const shortCode = `:${emoji}:`;

    content = (
      <img
        draggable='false'
        className='emojione custom-emoji'
        alt={shortCode}
        title={shortCode}
        src={filename}
      />
    );
  } else {
    const html = { __html: emojify(emoji) };
    content = <span dangerouslySetInnerHTML={html} />;
  }

  return (
    <div
      className='reaction_deck_container__row'
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
    >
      <span>
        <Icon id='bars' icon={MenuIcon} className='handle' />
      </span>
      <div className='reaction_deck__emoji'>
        <div className='reaction_deck__emoji__wrapper'>
          <div className='reaction_deck__emoji__wrapper__content'>
            <EmojiPickerDropdown onPickEmoji={handleChange} />
            <div>{content}</div>
          </div>
          <div className='reaction_deck__emoji__wrapper__options'>
            <Button secondary text={'Remove'} onClick={handleRemove} />
          </div>
        </div>
      </div>
    </div>
  );
};

export const ReactionDeck: React.FC<{
  multiColumn?: boolean;
}> = ({ multiColumn }) => {
  const dispatch = useAppDispatch();
  const intl = useIntl();

  const emojiMap = useAppSelector((state) => state.custom_emojis);
  const deck = useAppSelector((state) => state.reaction_deck);

  const onChange = useCallback(
    (emojis: any) => {
      dispatch(updateReactionDeck(emojis));
    },
    [dispatch],
  );

  const deckToArray = (deckData: any) =>
    deckData.map((item: any) => item.get('name')).toArray();

  /*
  const handleReorder = useCallback((result: any) => {
    const newDeck = deckToArray(deck);
    const deleted = newDeck.splice(result.source.index, 1);
    newDeck.splice(result.destination.index, 0, deleted[0]);
    onChange(newDeck);
  }, [onChange, deck]);
  */

  const handleChange = useCallback(
    (index: number, emoji: any) => {
      const newDeck = deckToArray(deck);
      newDeck[index] = emoji.native || emoji.id.replace(':', '');
      onChange(newDeck);
    },
    [onChange, deck],
  );

  const handleRemove = useCallback(
    (index: number) => {
      const newDeck = deckToArray(deck);
      newDeck.splice(index, 1);
      onChange(newDeck);
    },
    [onChange, deck],
  );

  const handleAdd = useCallback(
    (emoji: any) => {
      const newDeck = deckToArray(deck);
      const newEmoji = emoji.native || emoji.id.replace(':', '');
      newDeck.push(newEmoji);
      onChange(newDeck);
    },
    [onChange, deck],
  );

  const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 5,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  const handleDragStart = useCallback(
    (e: DragStartEvent) => {
      const { active } = e;

      setActiveId(active.id);
    },
    [setActiveId],
  );

  const handleDragEnd = useCallback(
    (e: DragEndEvent) => {
      const { active, over } = e;

      if (over && active.id !== over.id) {
        //onChange(deck);
      }

      setActiveId(null);
    },
    [dispatch, setActiveId],
  );

  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
  if (!deck) {
    return (
      <Column>
        <LoadingIndicator />
      </Column>
    );
  }

  return (
    <Column bindToDocument={!multiColumn}>
      <ColumnHeader
        icon='smile-o'
        iconComponent={EmojiReactionIcon}
        title={intl.formatMessage(messages.heading)}
        multiColumn={multiColumn}
        showBackButton
      />

      <DndContext
        sensors={sensors}
        collisionDetection={closestCenter}
        onDragStart={handleDragStart}
        onDragEnd={handleDragEnd}
      >
        <SortableContext items={deck.toArray()} strategy={rectSortingStrategy}>
          {deck.map((emoji: any, index) => (
            <div key={index} id={index.toString()}>
              <ReactionEmoji
                emojiMap={emojiMap}
                emoji={emoji.get('name')}
                index={index}
                onChange={handleChange}
                onRemove={handleRemove}
              />
            </div>
          ))}
        </SortableContext>

        <DragOverlay>{activeId ? <span>Test</span> : null}</DragOverlay>
      </DndContext>

      <div>
        <EmojiPickerDropdown
          onPickEmoji={handleAdd}
          button={
            <Button secondary>
              <FormattedMessage id='reaction_deck.add' defaultMessage='Add' />
            </Button>
          }
        />
      </div>

      <Helmet>
        <meta name='robots' content='noindex' />
      </Helmet>
    </Column>
  );
};

// eslint-disable-next-line import/no-default-export
export default ReactionDeck;
