// Copyright 2017-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import { join } from 'path';
import { existsSync } from 'fs';

import { BrowserWindow, app, Menu, Tray } from 'electron';
import * as DockIcon from '../ts/dock_icon';

import { LocaleMessagesType } from '../ts/types/I18N';

let trayContextMenu = null;
let tray: Tray | undefined;

export default function createTrayIcon(
  getMainWindow: () => BrowserWindow | undefined,
  messages: LocaleMessagesType
): { updateContextMenu: () => void; updateIcon: (count: number) => void } {
  let iconSize: string;
  switch (process.platform) {
    case 'darwin':
      iconSize = '16';
      break;
    case 'win32':
      iconSize = '32';
      break;
    default:
      iconSize = '256';
      break;
  }

  const iconNoNewMessages = join(
    __dirname,
    '..',
    'images',
    `icon_${iconSize}.png`
  );

  tray = new Tray(iconNoNewMessages);

  const forceOnTop = (mainWindow: BrowserWindow) => {
    if (mainWindow) {
      // On some versions of GNOME the window may not be on top when restored.
      // This trick should fix it.
      // Thanks to: https://github.com/Enrico204/Whatsapp-Desktop/commit/6b0dc86b64e481b455f8fce9b4d797e86d000dc1
      mainWindow.setAlwaysOnTop(true);
      mainWindow.focus();
      mainWindow.setAlwaysOnTop(false);
    }
  };

  const toggleWindowVisibility = () => {
    const mainWindow = getMainWindow();
    if (mainWindow) {
      if (mainWindow.isVisible()) {
        mainWindow.hide();
        DockIcon.hide();
      } else {
        mainWindow.show();
        DockIcon.show();

        forceOnTop(mainWindow);
      }
    }
    updateContextMenu();
  };

  const showWindow = () => {
    const mainWindow = getMainWindow();
    if (mainWindow) {
      if (!mainWindow.isVisible()) {
        mainWindow.show();
      }

      forceOnTop(mainWindow);
    }
    updateContextMenu();
  };

  const updateContextMenu = () => {
    const mainWindow = getMainWindow();

    // NOTE: we want to have the show/hide entry available in the tray icon
    // context menu, since the 'click' event may not work on all platforms.
    // For details please refer to:
    // https://github.com/electron/electron/blob/master/docs/api/tray.md.
    trayContextMenu = Menu.buildFromTemplate([
      {
        id: 'toggleWindowVisibility',
        label:
          messages[mainWindow && mainWindow.isVisible() ? 'hide' : 'show']
            .message,
        click: toggleWindowVisibility,
      },
      {
        id: 'quit',
        label: messages.quit.message,
        click: app.quit.bind(app),
      },
    ]);

    tray?.setContextMenu(trayContextMenu);
  };

  const updateIcon = (unreadCount: number) => {
    let image;

    if (unreadCount > 0) {
      const filename = `${String(unreadCount >= 10 ? 10 : unreadCount)}.png`;
      image = join(__dirname, '..', 'images', 'alert', iconSize, filename);
    } else {
      image = iconNoNewMessages;
    }

    if (!existsSync(image)) {
      console.log('tray.updateIcon: Image for tray update does not exist!');
      return;
    }
    try {
      tray?.setImage(image);
    } catch (error) {
      console.log(
        'tray.setImage error:',
        error && error.stack ? error.stack : error
      );
    }
  };

  tray.on('click', showWindow);

  tray.setToolTip(messages.signalDesktop.message);
  updateContextMenu();

  return {
    updateContextMenu,
    updateIcon,
  };
}