/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';
import { useCallback, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
/**
 * Internal dependencies
 */
import { KEYS } from '../../constants';
import { DROPDOWN_ITEM_PROP_TYPE } from '../types';
import { TypographyPresets } from '../typography';

export const MenuContainer = styled.ul`
  align-items: flex-start;
  background-color: ${({ theme }) => theme.colors.white};
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  margin: 0;
  min-width: 210px;
  overflow: hidden;
  padding: 5px 0;
  pointer-events: auto;

  & > a {
    background-color: none;
    text-decoration: none;
    &:focus {
      box-shadow: none; /*override common js */
    }
  }
`;
MenuContainer.propTypes = {
  isOpen: PropTypes.bool,
};

export const MenuItem = styled.li`
  ${TypographyPresets.Small};
  ${({ theme, isDisabled, isHovering, separator }) => `
    margin-bottom: 0; /* override common js */
    padding: 5px 25px;
    background: ${isHovering && !isDisabled ? theme.colors.gray25 : 'none'};
    color: ${isDisabled ? theme.colors.gray400 : theme.colors.gray700};
    cursor: ${isDisabled ? 'default' : 'pointer'};
    display: flex;
    width: 100%;

    &:focus, &:active, &:hover {
      color: ${isDisabled ? theme.colors.gray400 : theme.colors.gray700};
    }
    
    ${
      separator === 'top'
        ? `
        border-top: 1px solid ${theme.colors.gray50};
      `
        : ''
    }

    ${
      separator === 'bottom'
        ? `
        border-bottom: 1px solid ${theme.colors.gray50};
      `
        : ''
    }
  `}
`;

MenuItem.propTypes = {
  isDisabled: PropTypes.bool,
  isHovering: PropTypes.bool,
};

const MenuItemContent = styled.span`
  align-self: flex-start;
  height: 100%;
  margin: auto 0;
`;

const Menu = ({ isOpen, currentValueIndex = 0, items, onSelect }) => {
  const [hoveredIndex, setHoveredIndex] = useState(currentValueIndex);
  const listRef = useRef(null);

  // eslint-disable-next-line consistent-return
  useEffect(() => {
    if (isOpen) {
      const handleKeyDown = (event) => {
        switch (event.key) {
          case KEYS.UP:
            event.preventDefault();
            if (hoveredIndex > 0) {
              setHoveredIndex(hoveredIndex - 1);
              if (listRef.current) {
                listRef.current.children[hoveredIndex - 1].focus();
              }
            }
            break;

          case KEYS.DOWN:
            event.preventDefault();
            if (hoveredIndex < items.length - 1) {
              setHoveredIndex(hoveredIndex + 1);
              if (listRef.current) {
                listRef.current.children[hoveredIndex + 1].focus();
              }
            }
            break;

          case KEYS.ENTER:
            event.preventDefault();
            if (onSelect) {
              onSelect(items[hoveredIndex]);
            }
            break;

          default:
            break;
        }
      };

      document.addEventListener('keydown', handleKeyDown);
      return () => document.removeEventListener('keydown', handleKeyDown);
    }
  }, [hoveredIndex, items, onSelect, isOpen]);

  useEffect(() => {
    if (listRef.current && isOpen) {
      listRef.current[currentValueIndex]?.focus();
    }
    setHoveredIndex(currentValueIndex);
  }, [currentValueIndex, isOpen]);

  const renderMenuItem = useCallback(
    (item, index) => {
      const itemIsDisabled = !item.value && item.value !== 0;
      const MenuItemPropsAsLink = item.url
        ? {
            target: '_blank',
            rel: 'noreferrer',
            href: item.url,
            as: 'a',
          }
        : {};

      return (
        <MenuItem
          key={`${item.value}_${index}`}
          isHovering={index === hoveredIndex}
          onClick={() => !itemIsDisabled && onSelect && onSelect(item)}
          onMouseEnter={() => setHoveredIndex(index)}
          isDisabled={itemIsDisabled}
          separator={item.separator}
          {...MenuItemPropsAsLink}
        >
          <MenuItemContent>{item.label}</MenuItemContent>
        </MenuItem>
      );
    },
    [hoveredIndex, onSelect]
  );

  return (
    <MenuContainer ref={listRef}>
      {items.map((item, index) => renderMenuItem(item, index))}
    </MenuContainer>
  );
};

export const MenuProps = {
  items: PropTypes.arrayOf(DROPDOWN_ITEM_PROP_TYPE).isRequired,
  currentValueIndex: PropTypes.number,
  isOpen: PropTypes.bool,
  onSelect: PropTypes.func,
};

Menu.propTypes = MenuProps;

export default Menu;

@@ -1530,19 +1530,8 @@
 ring
-, separator
  %7D) 
@@ -1851,87 +1851,54 @@
    &
-:focus, &:active, &:hover %7B%0A      color: $%7BisDisabled ? theme.colors.gray400 : 
+.separatorTop %7B%0A      border-top: 1px solid $%7B
 them
@@ -1902,34 +1902,33 @@
 heme.colors.gray
-70
+5
 0%7D;%0A    %7D%0A    %0A 
@@ -1925,60 +1925,33 @@
   %7D%0A
-    
 %0A    
-$%7B%0A      separator === 'top'%0A        ? %60%0A  
+&.separatorBottom %7B%0A
     
@@ -1951,35 +1951,38 @@
  %7B%0A      border-
+bot
 to
-p
+m
 : 1px solid $%7Bth
@@ -2009,115 +2009,95 @@
     
-  %60
+%7D%0A
 %0A    
-    : ''%0A    %7D%0A%0A    $%7B%0A      separator === 'bottom'%0A        ? %60%0A        border-bottom: 1px solid $%7B
+&:focus, &:active, &:hover %7B%0A      color: $%7BisDisabled ? theme.colors.gray400 : 
 them
@@ -2109,25 +2109,26 @@
 ors.gray
-5
+70
 0%7D;%0A    
   %60%0A    
@@ -2123,30 +2123,12 @@
     
+%7D%0A
   
-%60%0A        : ''%0A    %7D
 %0A  %60
@@ -4488,33 +4488,153 @@
     
-separator=%7Bitem.separator
+className=%7B%0A            (item.separator === 'top' && 'separatorTop') %7C%7C%0A            (item.separator === 'bottom' && 'separatorBottom')%0A          
 %7D%0A  

use class names for adding borders to story menus instead of conditionalyl rendering in style to avoid menu items that do not use borders from having styles of `false:false`.