// @flow
import React, { useState, useCallback } from 'react';
import styled from 'styled-components';
import { useChannel } from '@storybook/api';
import { THEME_CHANGED } from './constants';
import { deriveStorybookTheme } from './storybook.theme';

import {
  themes,
  PatchworkThemeProvider,
  createWhitelabelTheme,
  Select,
  Option,
  Box,
} from '../../../../src';
import { CustomColorPicker } from './custom-color-picker';

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

const NarrowBox = styled(Box)`
  max-width: 700px;
`;

const deriveTheme = (selectedThemeOption, primary, secondary) => {
  if (selectedThemeOption !== 'custom') {
    return themes[selectedThemeOption];
  }
  return createWhitelabelTheme({ primary, secondary });
};

type ThemePanelProps = {
  api: { setOptions: ({ theme: mixed }) => void },
};
export const ThemePanel = ({ api }: ThemePanelProps) => {
  // DEFAULT_THEME_NAME is injected by webpack.
  /* eslint-disable no-undef */
  // $FlowFixMe
  const [themeName, setThemeName] = useState(DEFAULT_THEME_NAME);
  const [theme, setTheme] = useState(themes[DEFAULT_THEME_NAME]);
  /* eslint-enable no-undef */

  // Retain themes on story switch.
  const emit = useChannel({
    storyChanged: () => {
      api.setOptions({ theme: deriveStorybookTheme(theme) });
      emit(THEME_CHANGED, theme);
    },
    storiesConfigured: () => {
      api.setOptions({ theme: deriveStorybookTheme(theme) });
      emit(THEME_CHANGED, theme);
    },
  });

  const handleThemeChange = useCallback(
    newThemeName => {
      const newTheme = deriveTheme(newThemeName);
      setThemeName(newThemeName);
      setTheme(newTheme);
      emit(THEME_CHANGED, newTheme);
      api.setOptions({ theme: deriveStorybookTheme(newTheme) });
    },
    [emit, api],
  );

  const handlePrimaryColorChange = useCallback(
    newColorCode => {
      const newTheme = deriveTheme(
        themeName,
        newColorCode,
        theme.colorPalette['brand-secondary-base'],
      );
      setTheme(newTheme);
      emit(THEME_CHANGED, newTheme);
      api.setOptions({ theme: deriveStorybookTheme(newTheme) });
    },
    [api, emit, theme.colorPalette, themeName],
  );

  const handleSecondaryColorChange = useCallback(
    newColorCode => {
      const newTheme = deriveTheme(
        themeName,
        theme.colorPalette['brand-primary-base'],
        newColorCode,
      );
      setTheme(newTheme);
      emit(THEME_CHANGED, newTheme);
      api.setOptions({ theme: deriveStorybookTheme(newTheme) });
    },
    [api, emit, theme.colorPalette, themeName],
  );

  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 stacking="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>
  );
};
