import {detectCurrentLang, makeT, setAnonymousLocale} from 'app/client/lib/localization';
import {AppModel} from 'app/client/models/AppModel';
import {hoverTooltip} from 'app/client/ui/tooltips';
import {cssHoverCircle, cssTopBarBtn} from 'app/client/ui/TopBarCss';
import {icon} from 'app/client/ui2018/icons';
import {menu, menuItem} from 'app/client/ui2018/menus';
import {getCountryCode} from 'app/common/Locales';
import {getGristConfig} from 'app/common/urlUtils';
import {dom, makeTestId, styled} from 'grainjs';

const testId = makeTestId('test-language-');
const t = makeT('LanguageMenu');

export function buildLanguageMenu(appModel: AppModel) {
  // Get the list of languages from the config, or default to English.
  const languages = getGristConfig().supportedLngs ?? ['en'];
  // Get the current language (from user's preference, cookie or browser)
  const userLanguage = detectCurrentLang();

  if (appModel.currentValidUser) {
    // For logged in users, we don't need to show the menu (they have a preference in their profile).
    // But for tests we will show a hidden indicator.
    return dom('input', {type: 'hidden'}, (testId(`current-` + userLanguage)));
  }

  // When we switch language, we need to reload the page to get the new translations.
  // This button is only for anonymous users, so we don't need to save the preference or wait for anything.
  const changeLanguage = (lng: string) => {
    setAnonymousLocale(lng);
    window.location.reload();
  };
  // Try to convert locale setting to the emoji flag, fallback to plain flag icon.
  const emojiFlag = buildEmoji(userLanguage);
  return cssHoverCircle(
    // Margin is common for all hover buttons on TopBar.
    {style: `margin: 5px;`},
    // Flag or emoji flag if we have it.
    emojiFlag ?? cssTopBarBtn('Flag'),
    // Expose for test the current language use.
    testId(`current-` + userLanguage),
    menu(
      // Convert the list of languages we support to menu items.
      () => languages.map((lng) => menuItem(() => changeLanguage(lng), [
        // Try to convert the locale to nice name, fallback to locale itself.
        cssFirstUpper(translateLocale(lng) ?? lng),
        // If this is current language, mark it with a tick (by default we mark en).
        userLanguage === lng ? cssWrapper(icon('Tick'), testId('selected')) : null,
        testId(`lang-` + lng),
      ])),
      {
        placement: 'bottom-end',
      }
    ),
    hoverTooltip(t('Language'), {key: 'topBarBtnTooltip'}),
    testId('button'),
  );
}

// Unfortunately, Windows doesn't support emoji flags, so we need to use SVG icons.
function buildEmoji(locale: string) {
  const countryCode = getCountryCode(locale);
  if (!countryCode) { return null; }
  return [
    cssSvgIcon({
      style: `background-image: url("icons/locales/${countryCode}.svg")`
    }),
    dom.cls(cssSvgIconWrapper.className)
  ];
}

export function translateLocale(locale: string) {
  try {
    locale = locale.replace("_", "-");
    // This API might not be available in all browsers.
    const languageNames = new Intl.DisplayNames([locale], {type: 'language'});
    return languageNames.of(locale) || null;
  } catch (err) {
    return null;
  }
}

const cssWrapper = styled('div', `
  margin-left: auto;
  display: inline-block;
`);

const cssSvgIconWrapper = styled('div', `
  display: grid;
  place-content: center;
  cursor: pointer;
  user-select: none;
`);

const cssSvgIcon = styled('div', `
  width: 16px;
  height: 16px;
  background-repeat: no-repeat;
  background-position: center;
  background-color: transparent;
  background-size: contain;
`);

const cssFirstUpper = styled('span', `
  &::first-letter {
    text-transform: capitalize;
  }
`);