import React, { useCallback, useContext, useEffect, useMemo } from "react";
import chroma from "chroma-js";
import Select, { createFilter, Styles } from "react-select";
import LogListContext from "../../hooks/LogListContext";
import LogFilterChoiceContext from "../../hooks/LogFilterChoiceContext";
import { Config } from "react-select/src/filters";

import cssStyles from "./LogFilterSelector.module.sass";

export default function LogFilterSelector(props: {}) {
  const {filter, updateFilter} = useContext(LogListContext);
  const {channelNames, eventNames, characters} = useContext(LogFilterChoiceContext);

  const options = useMemo(() => [
    ...channelNames.map(n => ({type: 0, color: "#77BB77", value: n, label: n})),
    ...eventNames.map(n => ({type: 1, color: "#BB7777", value: n, label: n})),
    ...characters.map(c => ({type: 2, color: "#3377BB", value: c.id, label: c.name})),
  ], [channelNames, eventNames, characters])

  const value = useMemo(() => {
    const value = [];
    if (filter.characters && filter.characters.length > 0) {
      value.push(...filter.characters.map(ch => options.find(c => c.type === 2 && c.value === ch)))
    }
    if (filter.events && filter.events.length > 0) {
      value.push(...filter.events.map(v => options.find(c => c.type === 1 && c.value === v)))
    }
    if (filter.channels && filter.channels.length > 0) {
      value.push(...filter.channels.map(v => options.find(c => c.type === 0 && c.value === v)))
    }

    return value
  }, [filter, options])

  const setValue = useCallback((value: {type:number, value:string}[] ) => {
    if (value == null) {
      value = [];
    }

    updateFilter({
      ...filter,
      channels: value.filter(v => v.type === 0).map(v => v.value),
      events: value.filter(v => v.type === 1).map(v => v.value),
      characters: value.filter(v => v.type === 2).map(v => v.value),
    })
  }, [filter, updateFilter]);

  return (
    <Select
      className={cssStyles.multiSelect}
      closeMenuOnSelect={false}
      styles={colourStyles}
      filterOption={createFilter(filterConfig)}
      defaultValue={[]}
      isMulti={true}
      options={options}
      value={value}
      onChange={setValue}
      theme={defaultTheme => ({
        ...defaultTheme,
        colors: {
          ...defaultTheme.colors,
          ...customTheme,
        },
      })}
    />
  );
}

const customTheme = {
  "primary": "#333333",
  "primary75": "#333333",
  "primary50": "#333333",
  "primary25": "#333333",
  "danger": "#000000",
  "dangerLight": "#000000",
  "neutral0": "#000000",
  "neutral5": "#000000",
  "neutral10": "#000000",
  "neutral20": "#000000",
  "neutral30": "#000000",
  "neutral40": "#000000",
  "neutral50": "#000000",
  "neutral60": "#000000",
  "neutral70": "#000000",
  "neutral80": "#000000",
  "neutral90": "#000000",
}

const filterConfig: Config = {
  ignoreCase: true,
  ignoreAccents: true,
  trim: true,
  matchFrom: 'start',
};

const colourStyles: Styles = {
  control: styles => ({ ...styles, backgroundColor: 'rgba(0, 0, 0, 0.25)' }),
  option: (styles, { data, isDisabled, isFocused, isSelected }) => {
    const color = chroma(data.color);
    return {
      ...styles,
      backgroundColor: isDisabled
        ? null
        : isSelected
        ? data.color
        : isFocused
        ? color.alpha(0.1).css()
        : null,
      color: isDisabled
        ? '#ccc'
        : isSelected
        ? chroma.contrast(color, 'white') > 2
          ? 'white'
          : 'black'
        : data.color,
      cursor: isDisabled ? 'not-allowed' : 'default',

      ':active': {
        ...styles[':active'],
        backgroundColor: !isDisabled && (isSelected ? data.color : color.alpha(0.3).css()),
      },
    };
  },
  multiValue: (styles, { data }) => {
    const color = chroma(data.color);
    return {
      ...styles,
      backgroundColor: color.alpha(0.1).css(),
    };
  },
  multiValueLabel: (styles, { data }) => ({
    ...styles,
    color: data.color,
  }),
  multiValueRemove: (styles, { data }) => ({
    ...styles,
    color: data.color,
    ':hover': {
      backgroundColor: data.color,
      color: 'white',
    },
  }),
};
