/* eslint-disable no-unused-vars */
import { toTitleCase, toSingular } from '@vizality/util/string';
import { contextMenu, getModule } from '@vizality/webpack';
import React, { memo, useState, useEffect } from 'react';
import { FilterInput, Text } from '@vizality/components';
import { useForceUpdate } from '@vizality/hooks';
import { joinClassNames } from '@vizality/util/dom';
import { error } from '@vizality/util/logger';
import { useFilter } from '@vizality/hooks';
import { Messages } from '@vizality/i18n';

import { ContextMenu, LazyImage, TextBadge } from '..';

const { closeContextMenu } = contextMenu;

/**
 * @private
 */
const _labels = [ 'Component', 'Vizality', 'SettingsContextMenu' ];
const _error = (...message) => error({ labels: _labels, message });

/**
 * Vizality dashboard settings context menu that is like a mini-dashboard. You're able
 * to quickly access the Vizality dashboard and many of the pages that are
 * accessible on the Vizality dashboard.
 *
 * By default, this component is implemented and can be accessed in various places around
 * the app, such as the right click the gear on the user account panel which opens the
 * Discord settings context menu. It can also be accessed by right clicking on the
 * private channels Dashboard item.
 * @component
 * @returns {React.MemoExoticComponent<function(): React.ReactElement>}
 */
export default memo(() => {
  const [ quickToggle, setQuickToggle ] = useState(false);
  const forceUpdate = useForceUpdate();

  /**
   * Creates a sorted array containing all installed plugins.
   */
  const plugins = [ ...vizality.manager.plugins.values ];

  /**
   * Creates a sorted array containing all installed themes.
   */
  const themes = [ ...vizality.manager.themes.values ];


  /**
   * Set up our filter for plugins.
   */
  const [ pluginsQuery, setPluginsQuery, filteredPlugins ] = useFilter({
    keys: [ 'manifest.name' ],
    data: plugins
  });

  /**
   * Set up our filter for themes.
   */
  const [ themesQuery, setThemesQuery, filteredThemes ] = useFilter({
    keys: [ 'manifest.name' ],
    data: themes
  });

  /**
   * Add some key event listeners on mount to allow users to hold shift to enter
   * quick toggle mode on addon context items.
   */
  useEffect(() => {
    /**
     * Handles keydown events.
     * @param {document#event:keydown} evt Keydown event
     */
    const keyDownHandler = evt => {
      /**
       * Check for the shift key.
       */
      if (evt.keyCode === 16) {
        setQuickToggle(true);
      }
    };

    /**
     * Handles keyup events.
     * @param {document#event:keyup} evt Keyup event
     */
    const keyUpHandler = evt => {
      /**
       * Check for the shift key.
       */
      if (evt.keyCode === 16) {
        setQuickToggle(false);
      }
    };

    document.addEventListener('keydown', keyDownHandler);
    document.addEventListener('keyup', keyUpHandler);

    /**
     * Remove the event listeners on dismount.
     */
    return () => {
      document.removeEventListener('keydown', keyDownHandler);
      document.removeEventListener('keyup', keyUpHandler);
    };
  }, [ quickToggle ]);

  /**
   * Handles updating the current search filter.
   * @param {string} query Search query
   * @param {('plugins'|'themes')} type Addon type
   * @returns {void}
   */
  const handleQueryChange = (query, type) => {
    eval(`set${toTitleCase(type)}Query`)(typeof query === 'string' ? query : '');
  };

  const { noResultsImage } = getModule('noResultsImage');

  return (
    <ContextMenu.Menu navId='vizality-dashboard' onClose={closeContextMenu}>
      <ContextMenu.Item
        id='settings'
        label='Settings'
        action={() => vizality.api.routes.navigateTo('settings')}
      >
        <ContextMenu.Item
          id='general'
          label='General'
          action={() => vizality.api.routes.navigateTo('settings/general')}
        />
        <ContextMenu.Item
          id='account'
          label='Account'
          action={() => vizality.api.routes.navigateTo('settings/account')}
          disabled
        />
        <ContextMenu.Item
          id='appearance'
          label={() => (
            <>
              Appearance
              <TextBadge text='SOON™' />
            </>
          )}
          action={() => vizality.api.routes.navigateTo('settings/appearance')}
          disabled
        />
        <ContextMenu.Item
          id='notifications'
          label='Notifications'
          action={() => vizality.api.routes.navigateTo('settings/notifications')}
        />
        <ContextMenu.Item
          id='keybinds'
          label='Keybinds'
          action={() => vizality.api.routes.navigateTo('settings/keybinds')}
          disabled
        />
        <ContextMenu.Item
          id='commands'
          label='Commands'
          action={() => vizality.api.routes.navigateTo('settings/commands')}
        />
        <ContextMenu.Item
          id='developer'
          label='Developer'
          action={() => vizality.api.routes.navigateTo('settings/developer')}
        />
        <ContextMenu.Item
          id='advanced'
          label='Advanced'
          action={() => vizality.api.routes.navigateTo('settings/advanced')}
        />
      </ContextMenu.Item>
      {[ plugins, themes ].map((_, index) => {
        const type = index === 0 ? 'plugins' : 'themes';
        return (
          <ContextMenu.Item
            id={type}
            label={toTitleCase(type)}
            action={() => vizality.api.routes.navigateTo(type)}
          >
            <ContextMenu.Group
              id='search'
              className='vz-settings-context-menu-search'
              label={
                <FilterInput
                  value={eval(`${type}Query`)}
                  onChange={query => handleQueryChange(query, type)}
                  autoFocus
                />
              }
            >
              <ContextMenu.Separator />
              {eval(`filtered${toTitleCase(type)}`).length
                ? (
                  eval(`filtered${toTitleCase(type)}`).map(addon => {
                    const isEnabled = vizality.manager[type].isEnabled(addon.addonId);
                    const isInstalled = vizality.manager[type].isInstalled(addon.addonId);
                    const hasSettings = vizality.manager[type].hasSettings(addon.addonId);
                    const hasScreenshots = vizality.manager[type].hasScreenshots(addon.addonId);
                    const hasChangelog = vizality.manager[type].hasChangelog(addon.addonId);
                    return (
                      quickToggle
                        ? (
                          <ContextMenu.CheckboxItem
                            vz-addon-icon={addon.manifest.icon}
                            vz-addon-type={toSingular(type)}
                            id={addon.addonId}
                            label={addon.manifest.name}
                            checked={vizality.manager[type].isEnabled(addon.addonId)}
                            action={async () => {
                              try {
                                vizality.manager[type].isEnabled(addon.addonId)
                                  ? await vizality.manager[type].disable(addon.addonId)
                                  : await vizality.manager[type].enable(addon.addonId);
                                forceUpdate();
                              } catch (err) {
                                _error(err);
                              }
                            }}
                          >
                            <LazyImage src={addon.manifest.icon} />
                          </ContextMenu.CheckboxItem>
                        )
                        : (
                          <ContextMenu.Item
                            vz-addon-icon={addon.manifest.icon}
                            id={addon.addonId}
                            label={addon.manifest.name}
                            action={() => {
                              try {
                                return vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}`);
                              } catch (err) {
                                _error(err);
                              }
                            }}
                          >
                            <ContextMenu.Item
                              id='overview'
                              label='Overview'
                              action={() => vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}`)}
                            />
                            <ContextMenu.Item
                              id='screenshots'
                              label='Screenshots'
                              action={() => vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}/screenshots`)}
                              disabled={hasScreenshots}
                            />
                            <ContextMenu.Item
                              id='settings'
                              label='Settings'
                              action={() => vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}/settings`)}
                              disabled={isInstalled && hasSettings}
                            />
                            <ContextMenu.Item
                              id='reviews'
                              label='Reviews'
                              action={() => vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}/reviews`)}
                              disabled
                            />
                            <ContextMenu.Item
                              id='changelog'
                              label='Changelog'
                              action={() => vizality.api.routes.navigateTo(`/vizality/${toSingular(type)}/${addon.addonId}/changelog`)}
                              disabled={hasChangelog}
                            />
                            <ContextMenu.Separator />
                            {isInstalled && (
                              <ContextMenu.CheckboxItem
                                id='enable'
                                label='Enable'
                                checked={isEnabled}
                                action={async () => {
                                  vizality.manager[type].toggle(addon.addonId);
                                  forceUpdate();
                                }}
                              />
                            )}
                            {isInstalled
                              ? <ContextMenu.Item
                                id='uninstall'
                                label='Uninstall'
                                color={ContextMenu.Item.Colors.DANGER}
                                action={async () => vizality.manager[type].uninstall(addon.addonId)}
                              />
                              : <ContextMenu.Item
                                id='install'
                                label='Install'
                                color={ContextMenu.Item.Colors.GREEN}
                                action={async () => vizality.manager[type].install(addon.addonId)}
                              />
                            }
                            <ContextMenu.Separator />
                            <ContextMenu.Item
                              id='copy-link'
                              label='Copy Link'
                              action={() => void 0}
                            />
                            <ContextMenu.Item
                              id='copy-id'
                              label='Copy ID'
                              action={() => DiscordNative.clipboard.copy(addon.addonId)}
                            />
                          </ContextMenu.Item>
                        )
                    );
                  })
                )
                : (
                  <ContextMenu.Item
                    id='error-image'
                    disabled
                    label={() => (
                      <div className='vz-settings-context-menu-no-results'>
                        <Text className='vz-settings-context-menu-no-results-text' style={ { textAlign: 'center' } }>No {type} found</Text>
                        <div className={joinClassNames('vz-settings-context-menu-no-results-image', noResultsImage)} />
                      </div>
                    )}
                  />
                )
              }
            </ContextMenu.Group>
          </ContextMenu.Item>
        );
      })}
      <ContextMenu.Item
        id='snippets'
        label='Snippets'
        action={() => void 0}
        disabled
      />
      <ContextMenu.Item
        id='palettes'
        label='Palettes'
        action={() => void 0}
        disabled
      />
      {vizality.manager.builtins.isEnabled('quick-code') && (
        <ContextMenu.Item
          id='quick-code'
          label='Quick Code'
          action={() => vizality.api.routes.navigateTo('quick-code')}
        />
      )}
      <ContextMenu.Separator/>
      <ContextMenu.Item
        id='development'
        label='Development'
        action={() => vizality.api.routes.navigateTo('development')}
      >
        {/* @todo Addon Guidelines, Publish an Addon, Get Verified, Documentation, VSCode Snippets, Manifest Generator */}
        <ContextMenu.Item
          id='addon-guidelines'
          label='Addon Guidelines'
          action={() => void 0}
          disabled
        />
        <ContextMenu.Item
          id='publishing-an-addon'
          label='Publishing an Addon'
          action={() => void 0}
          disabled
        />
        <ContextMenu.Item
          id='becoming-verified'
          label='Becoming Verified'
          action={() => void 0}
          disabled
        />
        <ContextMenu.Item
          id='manifest-generator'
          label='Manifest Generator'
          action={() => void 0}
          disabled
        />
        <ContextMenu.Item
          id='documentation'
          label='Documentation'
          action={() => void 0}
        >
          <ContextMenu.Item
            id='getting-started'
            label='Getting Started'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='plugins'
            label='Plugins'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='themes'
            label='Themes'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='components'
            label='Components'
            action={() => void 0}
          >
            <ContextMenu.Item
              id='icon'
              label='Icon'
              action={() => vizality.api.routes.navigateTo('docs/components/icon')}
            />
            <ContextMenu.Item
              id='markdown'
              label='Markdown'
              action={() => vizality.api.routes.navigateTo('docs/components/markdown')}
            />
            <ContextMenu.Item
              id='error-boundary'
              label='Error Boundary'
              action={() => vizality.api.routes.navigateTo('docs/components/error-boundary')}
            />
            <ContextMenu.Item
              id='testing'
              label='Testing'
              action={() => vizality.api.routes.navigateTo('docs/components/test')}
            />
          </ContextMenu.Item>
          <ContextMenu.Item
            id='packages'
            label='Packages'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='api'
            label='API'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='advanced'
            label='Advanced'
            action={() => void 0}
            disabled
          />
          <ContextMenu.Item
            id='resources'
            label='Resources'
            action={() => void 0}
            disabled
          />
        </ContextMenu.Item>
      </ContextMenu.Item>
      <ContextMenu.Separator/>
      <ContextMenu.Item
        id='updater'
        label='Updater'
        action={() => vizality.api.routes.navigateTo('updater')}
      />
      <ContextMenu.Item
        id='changelog'
        label='Changelog'
        action={() => vizality.api.routes.navigateTo('changelog')}
      />
    </ContextMenu.Menu>
  );
});
