import React, { useState, useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import { buildClassName } from '../../../shared/utils/class-util';
import Icon from '../../../shared/components/icon';
import MultiRangeFilter from '../../components/multi-range-filter';
import { FlightFilterOptions } from '../../types';
import { selectTranslations } from '../booking/selectors';
import { formatMinutes } from './flight-utils';

interface FlightFilterProps {
  filterOptions: FlightFilterOptions;
  resultCount: number;

  applyFilter: (options: FlightFilterOptions) => void;
}

const FlightFilter: React.FC<FlightFilterProps> = ({ filterOptions, resultCount, applyFilter }) => {
  const translations = useSelector(selectTranslations);

  const [filtersVisible, setFiltersVisible] = useState<boolean>(false);
  const filterRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (filterRef.current && !filterRef.current.contains(event.target as Node)) {
        setFiltersVisible(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, []);

  const updateAirportFilter = (code: string) => {
    const updatedFilterOptions = {
      ...filterOptions,
      airports: filterOptions.airports.map((x) => {
        if (x.value !== code) return x;

        return {
          ...x,
          isSelected: !x.isSelected
        };
      })
    };

    applyFilter(updatedFilterOptions);
  };

  const updateAirlineFilter = (code: string) => {
    const updatedFilterOptions = {
      ...filterOptions,
      airlines: filterOptions.airlines.map((x) => {
        if (x.value !== code) return x;

        return {
          ...x,
          isSelected: !x.isSelected
        };
      })
    };

    applyFilter(updatedFilterOptions);
  };

  const updateStopsFilter = (count: string) => {
    const updatedFilterOptions = {
      ...filterOptions,
      numberOfStops: filterOptions.numberOfStops.map((x) => {
        if (x.value !== count) return x;

        return {
          ...x,
          isSelected: !x.isSelected
        };
      })
    };

    applyFilter(updatedFilterOptions);
  };

  const updateOutwardDeparture = (period: string) => {
    const updatedFilterOptions = {
      ...filterOptions,
      outward: {
        ...filterOptions.outward,
        departurePeriod: filterOptions.outward.departurePeriod.map((x) => {
          if (x.value !== period) return x;

          return {
            ...x,
            isSelected: !x.isSelected
          };
        })
      }
    };

    applyFilter(updatedFilterOptions);
  };

  const updateOutwardTravelDuration = (min: number, max: number) => {
    const updatedFilterOptions = {
      ...filterOptions,
      outward: {
        ...filterOptions.outward,
        travelDuration: {
          ...filterOptions.outward.travelDuration,
          selectedMin: min,
          selectedMax: max
        }
      }
    };

    applyFilter(updatedFilterOptions);
  };

  const updateOutwardChangeDuration = (min: number, max: number) => {
    const updatedFilterOptions = {
      ...filterOptions,
      outward: {
        ...filterOptions.outward,
        changeDuration: {
          ...filterOptions.outward.changeDuration,
          selectedMin: min,
          selectedMax: max
        }
      }
    };

    applyFilter(updatedFilterOptions);
  };

  const updateReturnDeparture = (period: string) => {
    const updatedFilterOptions = {
      ...filterOptions,
      return: {
        ...filterOptions.return,
        departurePeriod: filterOptions.return.departurePeriod.map((x) => {
          if (x.value !== period) return x;

          return {
            ...x,
            isSelected: !x.isSelected
          };
        })
      }
    };

    applyFilter(updatedFilterOptions);
  };

  const updateReturnTravelDuration = (min: number, max: number) => {
    const updatedFilterOptions = {
      ...filterOptions,
      return: {
        ...filterOptions.return,
        travelDuration: {
          ...filterOptions.return.travelDuration,
          selectedMin: min,
          selectedMax: max
        }
      }
    };

    applyFilter(updatedFilterOptions);
  };

  const updateReturnChangeDuration = (min: number, max: number) => {
    const updatedFilterOptions = {
      ...filterOptions,
      return: {
        ...filterOptions.return,
        changeDuration: {
          ...filterOptions.return.changeDuration,
          selectedMin: min,
          selectedMax: max
        }
      }
    };

    applyFilter(updatedFilterOptions);
  };

  return (
    <>
      <button type="button" className="cta cta--filter" onClick={() => setFiltersVisible(!filtersVisible)}>
        <Icon name="ui-filter" width={11} height={10} />
        <span>{translations.FLIGHTS_FORM.FILTER_OPTIONS}</span>
      </button>

      <div ref={filterRef} className={buildClassName(['flight__filter', filtersVisible && 'flight__filter--active'])}>
        <div className="flight__filter__header">
          <div className="flight__filter__header__title">
            <h3>{translations.FLIGHTS_FORM.FILTER_OPTIONS}</h3>
            <p>
              {translations.FLIGHTS_FORM.FLIGHTS_FOUND_1}{' '}
              <strong>
                {resultCount} {translations.FLIGHTS_FORM.FLIGHTS_FOUND_2}
              </strong>{' '}
              {translations.FLIGHTS_FORM.FLIGHTS_FOUND_3}
            </p>
          </div>
          <button type="button" className="cta cta--close" onClick={() => setFiltersVisible(false)}>
            <Icon name="ui-close" width={25} height={25} />
          </button>
        </div>
        <div className="flight__filter__body">
          <div className="flight__filter__group">
            <div className="flight__filter__group__title">{translations.FLIGHTS_FORM.AIRLINES}</div>
            <div className="flight__filter__group__wrapper">
              {filterOptions.airlines.map((option, k) => (
                <div className="tree" key={k}>
                  <div className="checkbox flight__filter__checkbox">
                    <label htmlFor={'airline_' + option.value} className="checkbox__label">
                      <input
                        type="checkbox"
                        id={'airline_' + option.value}
                        className="checkbox__input checkbox__input--parent"
                        onClick={() => updateAirlineFilter(option.value)}
                      />
                      <span className="radiobutton__label-text">
                        {option.label} {option.count > 0 && <span className="amount">({option.count})</span>}
                      </span>
                    </label>
                  </div>
                </div>
              ))}
            </div>
          </div>
          <div className="flight__filter__group">
            <div className="flight__filter__group__title">{translations.FLIGHTS_FORM.AIRPORTS}</div>
            <div className="flight__filter__group__wrapper">
              {filterOptions.airports.map((option, k) => (
                <div className="tree" key={k}>
                  <div className="checkbox flight__filter__checkbox">
                    <label htmlFor={'airport_' + option.value} className="checkbox__label">
                      <input
                        type="checkbox"
                        id={'airport_' + option.value}
                        className="checkbox__input checkbox__input--parent"
                        onClick={() => updateAirportFilter(option.value)}
                      />
                      <span className="radiobutton__label-text">
                        {option.label} {option.count > 0 && <span className="amount">({option.count})</span>}
                      </span>
                    </label>
                  </div>
                </div>
              ))}
            </div>
          </div>
          <div className="flight__filter__group">
            <div className="flight__filter__group__title">{translations.FLIGHTS_FORM.NUMBER_OF_STOPS}</div>
            <div className="flight__filter__group__wrapper">
              {filterOptions.numberOfStops.map((option, k) => (
                <div className="tree" key={k}>
                  <div className="checkbox flight__filter__checkbox">
                    <label htmlFor={'stops_' + option.value} className="checkbox__label">
                      <input
                        type="checkbox"
                        id={'stops_' + option.value}
                        className="checkbox__input checkbox__input--parent"
                        onClick={() => updateStopsFilter(option.value)}
                      />
                      <span className="radiobutton__label-text">
                        {option.label} {option.count > 0 && <span className="amount">({option.count})</span>}
                      </span>
                    </label>
                  </div>
                </div>
              ))}
            </div>
          </div>
          <div className="flight__filter__group">
            <div className="flight__filter__group__title">{translations.FLIGHTS_FORM.FLIGHT_OUTWARD}</div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.DEPARTURE_TIME}</p>
              {filterOptions.outward.departurePeriod.map((option, k) => (
                <div className="tree" key={k}>
                  <div className="checkbox flight__filter__checkbox">
                    <label htmlFor={'outward_time_' + option.value} className="checkbox__label">
                      <input
                        type="checkbox"
                        id={'outward_time_' + option.value}
                        className="checkbox__input checkbox__input--parent"
                        onClick={() => updateOutwardDeparture(option.value)}
                      />
                      <span className="radiobutton__label-text">
                        {option.label} {option.count > 0 && <span className="amount">({option.count})</span>}
                      </span>
                    </label>
                  </div>
                </div>
              ))}
            </div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.TRAVEL_DURATION}</p>
              <MultiRangeFilter
                min={filterOptions.outward.travelDuration.min}
                max={filterOptions.outward.travelDuration.max}
                selectedMin={filterOptions.outward.travelDuration.selectedMin}
                selectedMax={filterOptions.outward.travelDuration.selectedMax}
                valueFormatter={formatMinutes}
                onChange={updateOutwardTravelDuration}
              />
            </div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.CHANGE_TIME}</p>
              <MultiRangeFilter
                min={filterOptions.outward.changeDuration.min}
                max={filterOptions.outward.changeDuration.max}
                selectedMin={filterOptions.outward.changeDuration.selectedMin}
                selectedMax={filterOptions.outward.changeDuration.selectedMax}
                valueFormatter={formatMinutes}
                onChange={updateOutwardChangeDuration}
              />
            </div>
          </div>
          <div className="flight__filter__group">
            <div className="flight__filter__group__title">{translations.FLIGHTS_FORM.FLIGHT_RETURN}</div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.DEPARTURE_TIME}</p>
              {filterOptions.return.departurePeriod.map((option, k) => (
                <div className="tree" key={k}>
                  <div className="checkbox flight__filter__checkbox">
                    <label htmlFor={'return_time_' + option.value} className="checkbox__label">
                      <input
                        type="checkbox"
                        id={'return_time_' + option.value}
                        className="checkbox__input checkbox__input--parent"
                        onClick={() => updateReturnDeparture(option.value)}
                      />
                      <span className="radiobutton__label-text">
                        {option.label} {option.count > 0 && <span className="amount">({option.count})</span>}
                      </span>
                    </label>
                  </div>
                </div>
              ))}
            </div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.TRAVEL_DURATION}</p>
              <MultiRangeFilter
                min={filterOptions.return.travelDuration.min}
                max={filterOptions.return.travelDuration.max}
                selectedMin={filterOptions.return.travelDuration.selectedMin}
                selectedMax={filterOptions.return.travelDuration.selectedMax}
                valueFormatter={formatMinutes}
                onChange={updateReturnTravelDuration}
              />
            </div>
            <div className="flight__filter__group__wrapper">
              <p>{translations.FLIGHTS_FORM.CHANGE_TIME}</p>
              <MultiRangeFilter
                min={filterOptions.return.changeDuration.min}
                max={filterOptions.return.changeDuration.max}
                selectedMin={filterOptions.return.changeDuration.selectedMin}
                selectedMax={filterOptions.return.changeDuration.selectedMax}
                valueFormatter={formatMinutes}
                onChange={updateReturnChangeDuration}
              />
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default FlightFilter;
