import { addActionHandler, setGlobal } from '../../index';

import type { ApiError } from '../../../api/types';

import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../../util/environment';
import getReadableErrorText from '../../../util/getReadableErrorText';
import {
  selectBot, selectChatMessage, selectCurrentMessageList, selectIsTrustedBot,
} from '../../selectors';
import generateIdFor from '../../../util/generateIdFor';

const MAX_STORED_EMOJIS = 18; // Represents two rows of recent emojis

addActionHandler('toggleChatInfo', (global, action, payload) => {
  return {
    ...global,
    isChatInfoShown: payload !== undefined ? payload : !global.isChatInfoShown,
  };
});

addActionHandler('setLeftColumnWidth', (global, actions, payload) => {
  const leftColumnWidth = payload;

  return {
    ...global,
    leftColumnWidth,
  };
});

addActionHandler('resetLeftColumnWidth', (global) => {
  return {
    ...global,
    leftColumnWidth: undefined,
  };
});

addActionHandler('toggleManagement', (global) => {
  const { chatId } = selectCurrentMessageList(global) || {};

  if (!chatId) {
    return undefined;
  }

  return {
    ...global,
    management: {
      byChatId: {
        ...global.management.byChatId,
        [chatId]: {
          ...global.management.byChatId[chatId],
          isActive: !(global.management.byChatId[chatId] || {}).isActive,
        },
      },
    },
  };
});

addActionHandler('requestNextManagementScreen', (global, actions, payload) => {
  const { screen } = payload || {};
  const { chatId } = selectCurrentMessageList(global) || {};

  if (!chatId) {
    return undefined;
  }

  return {
    ...global,
    management: {
      byChatId: {
        ...global.management.byChatId,
        [chatId]: {
          ...global.management.byChatId[chatId],
          isActive: true,
          nextScreen: screen,
        },
      },
    },
  };
});

addActionHandler('closeManagement', (global) => {
  const { chatId } = selectCurrentMessageList(global) || {};

  if (!chatId) {
    return undefined;
  }

  return {
    ...global,
    management: {
      byChatId: {
        ...global.management.byChatId,
        [chatId]: {
          ...global.management.byChatId[chatId],
          isActive: false,
        },
      },
    },
  };
});

addActionHandler('openChat', (global) => {
  if (!IS_SINGLE_COLUMN_LAYOUT && !IS_TABLET_COLUMN_LAYOUT) {
    return undefined;
  }

  return {
    ...global,
    isLeftColumnShown: global.messages.messageLists.length === 0,
  };
});

addActionHandler('toggleStatistics', (global) => {
  return {
    ...global,
    isStatisticsShown: !global.isStatisticsShown,
    statistics: {
      ...global.statistics,
      currentMessageId: undefined,
    },
  };
});

addActionHandler('toggleMessageStatistics', (global, action, payload) => {
  return {
    ...global,
    statistics: {
      ...global.statistics,
      currentMessageId: payload?.messageId,
    },
  };
});

addActionHandler('toggleLeftColumn', (global) => {
  return {
    ...global,
    isLeftColumnShown: !global.isLeftColumnShown,
  };
});

addActionHandler('addRecentEmoji', (global, action, payload) => {
  const { emoji } = payload!;
  const { recentEmojis } = global;
  if (!recentEmojis) {
    return {
      ...global,
      recentEmojis: [emoji],
    };
  }

  const newEmojis = recentEmojis.filter((e) => e !== emoji);
  newEmojis.unshift(emoji);
  if (newEmojis.length > MAX_STORED_EMOJIS) {
    newEmojis.pop();
  }

  return {
    ...global,
    recentEmojis: newEmojis,
  };
});

addActionHandler('addRecentSticker', (global, action, payload) => {
  const { sticker } = payload;
  const { recent } = global.stickers;
  if (!recent) {
    return {
      ...global,
      stickers: {
        ...global.stickers,
        recent: {
          hash: '0',
          stickers: [sticker],
        },
      },
    };
  }

  const newStickers = recent.stickers.filter((s) => s.id !== sticker.id);
  newStickers.unshift(sticker);

  return {
    ...global,
    stickers: {
      ...global.stickers,
      recent: {
        ...recent,
        stickers: newStickers,
      },
    },
  };
});

addActionHandler('reorderStickerSets', (global, action, payload) => {
  const { order } = payload;
  return {
    ...global,
    stickers: {
      ...global.stickers,
      added: {
        setIds: order,
      },
    },
  };
});

addActionHandler('showNotification', (global, actions, payload) => {
  const notification = payload!;
  notification.localId = generateIdFor({});

  const newNotifications = [...global.notifications];
  const existingNotificationIndex = newNotifications.findIndex((n) => n.message === notification.message);
  if (existingNotificationIndex !== -1) {
    newNotifications.splice(existingNotificationIndex, 1);
  }

  newNotifications.push(notification);

  return {
    ...global,
    notifications: newNotifications,
  };
});

addActionHandler('dismissNotification', (global, actions, payload) => {
  const newNotifications = global.notifications.filter(({ localId }) => localId !== payload.localId);

  return {
    ...global,
    notifications: newNotifications,
  };
});

addActionHandler('showDialog', (global, actions, payload) => {
  const { data } = payload!;

  // Filter out errors that we don't want to show to the user
  if ('message' in data && data.hasErrorKey && !getReadableErrorText(data)) {
    return global;
  }

  const newDialogs = [...global.dialogs];
  if ('message' in data) {
    const existingErrorIndex = newDialogs.findIndex((err) => (err as ApiError).message === data.message);
    if (existingErrorIndex !== -1) {
      newDialogs.splice(existingErrorIndex, 1);
    }
  }

  newDialogs.push(data);

  return {
    ...global,
    dialogs: newDialogs,
  };
});

addActionHandler('dismissDialog', (global) => {
  const newDialogs = [...global.dialogs];

  newDialogs.pop();

  return {
    ...global,
    dialogs: newDialogs,
  };
});

addActionHandler('toggleSafeLinkModal', (global, actions, payload) => {
  const { url: safeLinkModalUrl } = payload;

  return {
    ...global,
    safeLinkModalUrl,
  };
});

addActionHandler('openHistoryCalendar', (global, actions, payload) => {
  const { selectedAt } = payload;

  return {
    ...global,
    historyCalendarSelectedAt: selectedAt,
  };
});

addActionHandler('closeHistoryCalendar', (global) => {
  return {
    ...global,
    historyCalendarSelectedAt: undefined,
  };
});

addActionHandler('openGame', (global, actions, payload) => {
  const { url, chatId, messageId } = payload;

  const message = selectChatMessage(global, chatId, messageId);
  if (!message) return;

  const botId = message.viaBotId || message.senderId;
  const bot = botId && selectBot(global, botId);
  if (!bot) return;

  if (!selectIsTrustedBot(global, bot)) {
    setGlobal({
      ...global,
      botTrustRequest: {
        bot,
        type: 'game',
        onConfirm: {
          action: 'openGame',
          payload,
        },
      },
    });
    return;
  }

  setGlobal({
    ...global,
    openedGame: {
      url,
      chatId,
      messageId,
    },
  });
});

addActionHandler('closeGame', (global) => {
  return {
    ...global,
    openedGame: undefined,
  };
});
