import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { ICategory } from '../../Interfaces/ICategory';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { TruncateString } from '../../utils/stringtools';
import { Category } from '../Category/Category';

interface ISidebarProps {
  selectedContainer: IContainerModel | undefined
  componentOptions: IAvailableContainer[]
  categories: ICategory[]
  isOpen: boolean
  buttonOnClick: (type: string) => void
}

function HandleDragStart(event: React.DragEvent<HTMLButtonElement>): void {
  event.dataTransfer.setData('type', (event.target as HTMLButtonElement).id);
}

interface SidebarCategory {
  category: ICategory
  children: JSX.Element[]
}

export function Sidebar(props: ISidebarProps): JSX.Element {
  const [hideDisabled, setHideDisabled] = React.useState<boolean>(false);

  const rootElements: Array<JSX.Element | undefined> = [];
  const categories = new Map<string, SidebarCategory>(props.categories.map(category => [
    category.Type,
    {
      category,
      children: []
    }
  ]));

  // build the categories (sorted with categories first)
  categories.forEach((categoryWrapper, categoryName) => {
    rootElements.push(
      <Category
        key={categoryName}
        category={categoryWrapper.category}
      >
        { categoryWrapper.children }
      </Category>);
  });

  const selectedContainer = props.selectedContainer;
  const config = props.componentOptions.find(option => option.Type === selectedContainer?.properties.type);
  // build the components
  props.componentOptions.forEach(componentOption => {
    if (componentOption.IsHidden === true) {
      return;
    }

    let disabled = false;
    if (config?.Whitelist !== undefined) {
      disabled = config.Whitelist?.find(type => type === componentOption.Type) === undefined;
    } else if (config?.Blacklist !== undefined) {
      disabled = config.Blacklist?.find(type => type === componentOption.Type) !== undefined ?? false;
    }

    if (disabled && hideDisabled) {
      return;
    }

    const componentButton = (<button
      key={componentOption.Type}
      type="button"
      className='w-full justify-center h-16 transition-all sidebar-component'
      id={componentOption.Type}
      title={componentOption.Type}
      onClick={() => props.buttonOnClick(componentOption.Type)}
      draggable={true}
      onDragStart={(event) => HandleDragStart(event)}
      disabled={disabled}
    >
      {TruncateString(componentOption.DisplayedText ?? componentOption.Type, 25)}
    </button>);

    if (componentOption.Category === null || componentOption.Category === undefined) {
      rootElements.push(componentButton);
      return;
    }

    const category = categories.get(componentOption.Category);
    if (category === undefined) {
      console.error(`[Category] Category does not exists in configuration.Categories: ${componentOption.Category}`);
      return;
    }

    category.children.push(componentButton);
  });

  const isOpenClasses = props.isOpen ? 'left-16' : '-left-64';
  return (
    <div className={`fixed z-10 bg-slate-200
      text-gray-700 transition-all h-full w-64
      overflow-y-auto ${isOpenClasses}`}>
      <div className='bg-slate-100 sidebar-title flex place-content-between'>
          Components
        <button
          onClick={() => { setHideDisabled(!hideDisabled); }}
          className='h-6'
          aria-label='Hide disabled component'
          title='Hide disabled component'
        >
          {
            hideDisabled
              ? <EyeSlashIcon className='heroicon' />
              : <EyeIcon className='heroicon' />
          }
        </button>
      </div>
      <div className='transition-all grid grid-cols-1 md:grid-cols-1 gap-2
         m-2 md:text-xs font-bold'>
        {rootElements}
      </div>
    </div>
  );
};
