import React from 'react';

import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import {
  Dropdown,
  Form,
  Stack,
} from 'react-bootstrap';

import {
  payloadDisplayByValue,
  PayloadTypeIcon,
  routeDisplayByValue,
} from './MeshCoreData';

interface FilterDropdownProps {
  label: string;
  options: number[];
  selectedValues: Set<number>;
  getLabelForValue: (value: number) => string;
  getIconForValue?: (value: number) => React.ReactElement;
  onToggle: (value: number, isChecked: boolean) => void;
  onSelectAll: () => void;
}

const FilterDropdown: React.FC<FilterDropdownProps> = ({
  label,
  options,
  selectedValues,
  getLabelForValue,
  getIconForValue,
  onToggle,
  onSelectAll,
}) => {
  const isAllSelected = selectedValues.size === 0;
  const displayLabel = isAllSelected ? `${label}: All` : `${label}: ${selectedValues.size} selected`;

  return (
    <Dropdown className="meshcore-filter-dropdown">
      <Dropdown.Toggle variant="outline-light" size="sm" className="meshcore-dropdown-toggle">
        {displayLabel}
        <ExpandMoreIcon style={{ fontSize: '1rem', marginLeft: '0.25rem' }} />
      </Dropdown.Toggle>

      <Dropdown.Menu className="meshcore-dropdown-menu">
        <Dropdown.Item as="label" className="meshcore-dropdown-item">
          <Form.Check
            type="checkbox"
            label="All"
            checked={isAllSelected}
            onChange={() => onSelectAll()}
            className="mb-0"
            onClick={(e) => e.stopPropagation()}
          />
        </Dropdown.Item>
        <Dropdown.Divider />
        {options.map((option) => (
          <Dropdown.Item key={option} as="label" className="meshcore-dropdown-item">
            <Form.Check
              type="checkbox"
              label={(
                <span>
                  {getIconForValue && <span style={{ marginRight: '0.5rem' }}>{getIconForValue(option)}</span>}
                  {getLabelForValue(option)}
                </span>
              )}
              checked={selectedValues.has(option)}
              onChange={(e) => onToggle(option, e.target.checked)}
              className="mb-0"
              onClick={(e) => e.stopPropagation()}
            />
          </Dropdown.Item>
        ))}
      </Dropdown.Menu>
    </Dropdown>
  );
};

interface StringFilterDropdownProps {
  label: string;
  options: string[];
  selectedValues: Set<string>;
  onToggle: (value: string, isChecked: boolean) => void;
  onSelectAll: () => void;
}

const StringFilterDropdown: React.FC<StringFilterDropdownProps> = ({
  label,
  options,
  selectedValues,
  onToggle,
  onSelectAll,
}) => {
  const isAllSelected = selectedValues.size === 0;
  const displayLabel = isAllSelected ? `${label}: All` : `${label}: ${selectedValues.size} selected`;

  return (
    <Dropdown className="meshcore-filter-dropdown">
      <Dropdown.Toggle variant="outline-light" size="sm" className="meshcore-dropdown-toggle">
        {displayLabel}
        <ExpandMoreIcon style={{ fontSize: '1rem', marginLeft: '0.25rem' }} />
      </Dropdown.Toggle>

      <Dropdown.Menu className="meshcore-dropdown-menu">
        <Dropdown.Item as="label" className="meshcore-dropdown-item">
          <Form.Check
            type="checkbox"
            label="All"
            checked={isAllSelected}
            onChange={() => onSelectAll()}
            className="mb-0"
            onClick={(e) => e.stopPropagation()}
          />
        </Dropdown.Item>
        <Dropdown.Divider />
        {options.map((option) => (
          <Dropdown.Item key={option} as="label" className="meshcore-dropdown-item">
            <Form.Check
              type="checkbox"
              label={option}
              checked={selectedValues.has(option)}
              onChange={(e) => onToggle(option, e.target.checked)}
              className="mb-0"
              onClick={(e) => e.stopPropagation()}
            />
          </Dropdown.Item>
        ))}
      </Dropdown.Menu>
    </Dropdown>
  );
};

interface MeshCorePacketFiltersProps {
  uniquePayloadTypes: number[];
  uniqueRadioNames: string[];
  uniqueRouteTypes: number[];
  filterPayloadTypes: Set<number>;
  filterRadios: Set<string>;
  filterRouteTypes: Set<number>;
  onPayloadToggle: (value: number, isChecked: boolean) => void;
  onPayloadSelectAll: () => void;
  onRadioToggle: (value: string, isChecked: boolean) => void;
  onRadioSelectAll: () => void;
  onRouteToggle: (value: number, isChecked: boolean) => void;
  onRouteSelectAll: () => void;
}

const MeshCorePacketFilters: React.FC<MeshCorePacketFiltersProps> = ({
  uniquePayloadTypes,
  uniqueRadioNames,
  uniqueRouteTypes,
  filterPayloadTypes,
  filterRadios,
  filterRouteTypes,
  onPayloadToggle,
  onPayloadSelectAll,
  onRadioToggle,
  onRadioSelectAll,
  onRouteToggle,
  onRouteSelectAll,
}) => {
  return (
    <div className="meshcore-filters p-2 border-bottom border-secondary-subtle">
      <Stack direction="horizontal" gap={2}>
        <FilterDropdown
          label="Payload Type"
          options={uniquePayloadTypes}
          selectedValues={filterPayloadTypes}
          getLabelForValue={(value) => payloadDisplayByValue[value] ?? `0x${value.toString(16)}`}
          getIconForValue={(value) => <PayloadTypeIcon payloadType={value} />}
          onToggle={onPayloadToggle}
          onSelectAll={onPayloadSelectAll}
        />
        <StringFilterDropdown
          label="Radio"
          options={uniqueRadioNames}
          selectedValues={filterRadios}
          onToggle={onRadioToggle}
          onSelectAll={onRadioSelectAll}
        />
        <FilterDropdown
          label="Route Type"
          options={uniqueRouteTypes}
          selectedValues={filterRouteTypes}
          getLabelForValue={(value) => routeDisplayByValue[value] ?? `0x${value.toString(16)}`}
          onToggle={onRouteToggle}
          onSelectAll={onRouteSelectAll}
        />
      </Stack>
    </div>
  );
};

export default MeshCorePacketFilters;
