// @flow
import React, { type ComponentType } from 'react';
import styled from 'styled-components';
import { CustomColorPicker } from './custom-color-picker';
import { useLocalStorage } from './use-local-storage';
import {
  themes,
  type ThemeName,
  PatchworkThemeProvider,
  createWhitelabelTheme,
  Select,
  Option,
  Box,
  type BoxProps,
} from '../../../../src';

const themeNames: ThemeName[] = [...Object.keys(themes), 'custom'];

const NarrowBox: ComponentType<BoxProps> = styled(Box)`
  max-width: 700px;
`;

function deriveTheme(selectedThemeOption: ThemeName, primary, secondary) {
  if (selectedThemeOption !== 'custom') {
    return themes[selectedThemeOption];
  }
  return createWhitelabelTheme({ name: 'custom', primary, secondary });
}

export const ThemePanel = () => {
  const [themeName, setThemeName] = useLocalStorage<ThemeName>(
    'themeName',
    /* eslint-disable no-undef */
    // $FlowFixMe
    DEFAULT_THEME_NAME, // injected by webpack.
    /* eslint-enable no-undef */
  );
  const [theme, setTheme] = useLocalStorage('theme', themes[themeName]);

  const updateTheme = (newThemeName: ThemeName, newTheme) => {
    setThemeName(newThemeName);
    setTheme(newTheme);

    // There appears to be no good way to get the DocsContainer to
    // change its theme dynamically in storybook 5. They claim there's
    // a fix in 6 but that's not released yet. For now, the simplest way
    // to upate the theme in the manager chrome, the story, and the docs
    // container is to update localstorage and then reload the page.
    // https://github.com/storybookjs/storybook/issues/10523
    window.location.reload();
  };

  const handleThemeChange = (newThemeName) => {
    if (newThemeName == null) return;
    if (!themeNames.includes(newThemeName)) return;
    // $FlowFixMe we don't want to check against all string literals
    updateTheme(newThemeName, deriveTheme(newThemeName));
  };

  const handlePrimaryColorChange = (newColorCode) => {
    updateTheme(
      themeName,
      deriveTheme(
        themeName,
        newColorCode,
        theme.colorPalette['brand-secondary-base'],
      ),
    );
  };

  const handleSecondaryColorChange = (newColorCode) => {
    updateTheme(
      themeName,
      deriveTheme(
        themeName,
        theme.colorPalette['brand-primary-base'],
        newColorCode,
      ),
    );
  };

  return (
    <PatchworkThemeProvider theme={theme}>
      <NarrowBox spacing={['mv2', 'mhauto']}>
        <Select
          onChange={handleThemeChange}
          value={themeName}
          label="Choose a Theme"
        >
          {themeNames.map((name) => (
            <Option value={name} key={name}>
              {name}
            </Option>
          ))}
        </Select>
        {themeName === 'custom' && (
          <Box stacked="column" spacing="mv2">
            <CustomColorPicker
              onColorChange={handlePrimaryColorChange}
              label="Primary Color"
              value={theme.colorPalette['brand-primary-base']}
            />
            <CustomColorPicker
              onColorChange={handleSecondaryColorChange}
              label="Secondary Color"
              value={theme.colorPalette['brand-secondary-base']}
            />
          </Box>
        )}
      </NarrowBox>
    </PatchworkThemeProvider>
  );
};
