import * as React from 'react';
import { css } from '@emotion/core';
import styled from '@emotion/styled';
import { Popover } from '@lightspeed/flame/Popover';
import { Flex } from '@lightspeed/flame/Core';
import { IconSmallChevronDown } from '@lightspeed/flame/Icon/SmallChevronDown';
import { Logo as CirrusLogo } from '@lightspeed/cirrus-ls-logo';
import { themeGet } from '@styled-system/theme-get';

import { PAGE_HEADER_HEIGHT } from '../../styles/constants';

import Topbar from './components/Topbar';
import ecomLogo from './logos/ecom';
import retailLogo from './logos/retail';

const baseApps = {
  ecom: ecomLogo,
  retail: retailLogo,
};

function getAppImageByName(name: string, config = {}) {
  const appImages = {
    ...baseApps,
    ...config,
  };

  // @ts-ignore
  return appImages[name];
}

const LogoLink = styled('a')`
  height: ${PAGE_HEADER_HEIGHT}px;
  display: flex;
  justify-content: center;
  align-items: center;
  outline: 0;
  padding-left: ${themeGet('space.2')};
  padding-top: ${themeGet('space.2')};
  padding-bottom: ${themeGet('space.2')};
`;

const LogoWrapper = styled('div')`
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  padding-right: 9px;

  &::after {
    content: '';
    position: absolute;
    right: -1px;
    background-color: ${themeGet('colors.danger')};
    height: 16px;
    width: 1px;
  }
`;

const Logo: React.FC<React.HTMLProps<HTMLAnchorElement>> = props => (
  <LogoLink {...props}>
    <LogoWrapper>
      <CirrusLogo color="red-white" width="116px" />
    </LogoWrapper>
  </LogoLink>
);

const currentProductShared = (props: { theme: any }) => css`
  padding: 4px 0 0 8px;
  fill: ${themeGet('colors.white')(props)};
`;

const CurrentProduct = styled('div')(currentProductShared);

const ProductSwitchButton = styled('button')`
  ${currentProductShared}
  height: ${PAGE_HEADER_HEIGHT}px;
  display: flex;
  flex-grow: 1;
  align-items: center;
  justify-content: space-between;
  background-color: ${themeGet('sidebarStyles.background')};
  border: 0;
  cursor: pointer;
  outline: 0;
`;

const SwitchButtonWithRef = React.forwardRef<HTMLButtonElement>((props, ref) => (
  <ProductSwitchButton {...props} ref={ref} />
));

const AppSwitcherPopover = styled(Popover)`
  top: 0 !important;
  left: auto !important;
  right: ${themeGet('space.2')};
  transform: none !important;
  margin-top: 11px !important;
  width: 95px;
  overflow: hidden;
`;

const PopoverItem = styled('a')`
  fill: ${themeGet('colors.secondary')};
  cursor: pointer;
  padding: ${themeGet('space.2')};
  font-size: ${themeGet('fontSizes.text-xs')};
  line-height: 1;
  display: block;

  &:active,
  &:hover,
  &:focus {
    background-color: ${themeGet('colors.secondary')};
    font-weight: normal;
    color: ${themeGet('colors.white')};
    fill: ${themeGet('colors.white')};
  }
`;

const AppSwitcherIcon = styled(IconSmallChevronDown)`
  margin-right: ${themeGet('space.2')};
  opacity: 0.5;
`;

interface AppSwitcherProps {
  currentProduct?: string;
  appsConfig?: any;
  logoProps?: any;
  canSwitchTo?: {
    name: string;
    href?: string;
    image?: string;
    onClick?: (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void;
  }[];
  triggerProps?: any;
}
interface AppSwitcherState {
  isOpen: boolean;
}
// eslint-disable-next-line react/no-multi-comp
class AppSwitcher extends React.Component<AppSwitcherProps, AppSwitcherState> {
  // eslint-disable-next-line react/sort-comp
  popperRef: any;

  constructor(props: AppSwitcherProps) {
    super(props);

    this.state = { isOpen: false };

    this.handleOpen = this.handleOpen.bind(this);
    this.handleClose = this.handleClose.bind(this);
    this.handleClickOutside = this.handleClickOutside.bind(this);
    this.registerPopperWrapper = this.registerPopperWrapper.bind(this);
    this.getSwitchableApps = this.getSwitchableApps.bind(this);
  }

  componentWillUnmount() {
    document.removeEventListener('click', this.handleClickOutside);
  }

  handleClickOutside(e: Event) {
    const { target } = e;

    if (this.popperRef && !this.popperRef.contains(target)) {
      this.handleClose();
      document.removeEventListener('click', this.handleClickOutside);
    }
  }

  handleOpen() {
    this.setState(() => ({
      isOpen: true,
    }));

    document.addEventListener('click', this.handleClickOutside);
  }

  handleClose() {
    this.setState(() => ({
      isOpen: false,
    }));
  }

  registerPopperWrapper(node: React.ReactNode) {
    this.popperRef = node;
  }

  getSwitchableApps() {
    const { appsConfig, currentProduct } = this.props;
    const appsWithoutCurrent = this.props.canSwitchTo.filter(({ name }) => name !== currentProduct);
    const appsList = [{ name: currentProduct }, ...appsWithoutCurrent];

    return appsList.map(({ name, ...rest }) => ({
      ...rest,
      name,
      image: getAppImageByName(name, appsConfig),
    }));
  }

  render() {
    const { isOpen } = this.state;
    const { currentProduct, appsConfig, logoProps, canSwitchTo, triggerProps } = this.props;
    const currentProductImage = getAppImageByName(currentProduct, appsConfig);
    const canSwitch = canSwitchTo.length > 0;
    const switchableApps = this.getSwitchableApps();

    return (
      <Topbar>
        <Flex
          alignItems="center"
          css={{
            overflowX: 'hidden',
          }}
        >
          <Logo {...logoProps} />

          {canSwitch ? (
            <Flex ref={this.registerPopperWrapper} flexGrow={1}>
              <AppSwitcherPopover
                autoClose={false}
                isOpen={isOpen}
                onOpen={this.handleOpen}
                onClose={this.handleClose}
                target={({
                  targetProps,
                  targetEvents,
                }: {
                  targetProps: any;
                  targetEvents: any;
                }) => (
                  <SwitchButtonWithRef {...targetProps} {...triggerProps} {...targetEvents}>
                    {currentProductImage}
                    <AppSwitcherIcon name="small-chevron-down" color="white" />
                  </SwitchButtonWithRef>
                )}
                noArrow
              >
                {switchableApps.map(({ name, image, onClick = () => {}, ...restProps }) => (
                  <PopoverItem
                    key={name}
                    {...restProps}
                    onClick={e => {
                      onClick(e);
                      this.handleClose();
                    }}
                  >
                    {image}
                  </PopoverItem>
                ))}
              </AppSwitcherPopover>
            </Flex>
          ) : (
            <CurrentProduct {...triggerProps}>{currentProductImage}</CurrentProduct>
          )}
        </Flex>
      </Topbar>
    );
  }
}

(AppSwitcher as any).defaultProps = {
  canSwitchTo: [],
  triggerProps: {},
};

export default AppSwitcher;
