// @flow
import { SEARCH_OPTIONS, SEARCH_PAGE_SIZE } from 'constants/search';
import * as ICONS from 'constants/icons';
import React, { useMemo } from 'react';
import { Form, FormField } from 'component/common/form';
import Button from 'component/button';
import Icon from 'component/common/icon';
import classnames from 'classnames';

const CLAIM_TYPES = {
  [SEARCH_OPTIONS.INCLUDE_FILES]: 'Files',
  [SEARCH_OPTIONS.INCLUDE_CHANNELS]: 'Channels',
  [SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS]: 'Everything',
};

const TYPES_ADVANCED = {
  [SEARCH_OPTIONS.MEDIA_VIDEO]: 'Video',
  [SEARCH_OPTIONS.MEDIA_AUDIO]: 'Audio',
  [SEARCH_OPTIONS.MEDIA_IMAGE]: 'Image',
  [SEARCH_OPTIONS.MEDIA_TEXT]: 'Text',
  [SEARCH_OPTIONS.MEDIA_APPLICATION]: 'Other',
};

const TIME_FILTER = {
  '': 'All',
  // [SEARCH_OPTIONS.TIME_FILTER_LAST_HOUR]: 'Last Hour', -- disable (doesn't work)
  [SEARCH_OPTIONS.TIME_FILTER_TODAY]: 'Last 24 Hours',
  [SEARCH_OPTIONS.TIME_FILTER_THIS_WEEK]: 'This Week',
  [SEARCH_OPTIONS.TIME_FILTER_THIS_MONTH]: 'This Month',
  [SEARCH_OPTIONS.TIME_FILTER_THIS_YEAR]: 'This Year',
};

const SORT_BY = {
  '': 'Relevance',
  [SEARCH_OPTIONS.SORT_DESCENDING]: 'Newest first',
  [SEARCH_OPTIONS.SORT_ACCENDING]: 'Oldest first',
};

type Props = {
  setSearchOption: (string, boolean | string | number) => void,
  options: {},
  simple: boolean,
  expanded: boolean,
  toggleSearchExpanded: () => void,
  onSearchOptionsChanged: (string) => void,
};

const SearchOptions = (props: Props) => {
  const { options, simple, setSearchOption, expanded, toggleSearchExpanded, onSearchOptionsChanged } = props;

  const stringifiedOptions = JSON.stringify(options);

  const isFilteringByChannel = useMemo(() => {
    const jsonOptions = JSON.parse(stringifiedOptions);
    const claimType = String(jsonOptions[SEARCH_OPTIONS.CLAIM_TYPE] || '');
    return claimType.includes(SEARCH_OPTIONS.INCLUDE_CHANNELS);
  }, [stringifiedOptions]);

  if (simple) {
    delete TYPES_ADVANCED[SEARCH_OPTIONS.MEDIA_APPLICATION];
    delete TYPES_ADVANCED[SEARCH_OPTIONS.MEDIA_IMAGE];
  }

  React.useEffect(() => {
    // We no longer let the user set the search results count, but the value
    // will be in local storage for existing users. Override that.
    if (options[SEARCH_OPTIONS.RESULT_COUNT] !== SEARCH_PAGE_SIZE) {
      setSearchOption(SEARCH_OPTIONS.RESULT_COUNT, SEARCH_PAGE_SIZE);
    }
  }, []);

  function updateSearchOptions(option, value) {
    setSearchOption(option, value);
    if (onSearchOptionsChanged) {
      onSearchOptionsChanged(option);
    }
  }

  function addRow(label: string, value: any) {
    return (
      <tr>
        <td>
          <legend className="search__legend">{label}</legend>
        </td>
        <td>{value}</td>
      </tr>
    );
  }

  const OBJ_TO_OPTION_ELEM = (obj) => {
    return Object.entries(obj).map((x) => {
      return (
        <option key={x[0]} value={x[0]}>
          {__(String(x[1]))}
        </option>
      );
    });
  };

  const typeElem = (
    <>
      <div className="filter-values">
        <div>
          {Object.entries(CLAIM_TYPES).map((t) => {
            const option = t[0];
            if (option === SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS) {
              return null;
            }
            return (
              <Button
                key={option}
                button="alt"
                label={t[1]}
                className={classnames(`button-toggle`, {
                  'button-toggle--active': options[SEARCH_OPTIONS.CLAIM_TYPE] === option,
                })}
                onClick={() => setSearchOption(SEARCH_OPTIONS.CLAIM_TYPE, option)}
              />
            );
          })}
        </div>
        <Button
          button="close"
          className={classnames('close-button', {
            'close-button--visible': options[SEARCH_OPTIONS.CLAIM_TYPE] !== SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS,
          })}
          icon={ICONS.REMOVE}
          onClick={() => updateSearchOptions(SEARCH_OPTIONS.CLAIM_TYPE, SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS)}
        />
      </div>
      {options[SEARCH_OPTIONS.CLAIM_TYPE] === SEARCH_OPTIONS.INCLUDE_FILES && (
        <div className="media-types">
          {Object.entries(TYPES_ADVANCED).map((t) => {
            const option = t[0];
            return (
              <FormField
                key={option}
                name={option}
                type="checkbox"
                blockWrap={false}
                disabled={options[SEARCH_OPTIONS.CLAIM_TYPE] !== SEARCH_OPTIONS.INCLUDE_FILES}
                label={t[1]}
                checked={!isFilteringByChannel && options[option]}
                onChange={() => updateSearchOptions(option, !options[option])}
              />
            );
          })}
        </div>
      )}
    </>
  );

  const otherOptionsElem = (
    <>
      <div className="filter-values">
        <FormField
          type="checkbox"
          name="exact-match"
          checked={options[SEARCH_OPTIONS.EXACT]}
          onChange={() => updateSearchOptions(SEARCH_OPTIONS.EXACT, !options[SEARCH_OPTIONS.EXACT])}
          label={__('Exact match')}
        />
        <Icon
          className="icon--help"
          icon={ICONS.HELP}
          tooltip
          size={16}
          customTooltipText={__(
            'Find results that include all the given words in the exact order.\nThis can also be done by surrounding the search query with quotation marks (e.g. "hello world").'
          )}
        />
      </div>
    </>
  );

  const uploadDateElem = (
    <div className="filter-values">
      <FormField
        type="select"
        name="upload-date"
        value={options[SEARCH_OPTIONS.TIME_FILTER]}
        onChange={(e) => updateSearchOptions(SEARCH_OPTIONS.TIME_FILTER, e.target.value)}
        blockWrap={false}
      >
        {OBJ_TO_OPTION_ELEM(TIME_FILTER)}
      </FormField>
      <Button
        button="close"
        className={classnames('close-button', {
          'close-button--visible': options[SEARCH_OPTIONS.TIME_FILTER],
        })}
        icon={ICONS.REMOVE}
        onClick={() => updateSearchOptions(SEARCH_OPTIONS.TIME_FILTER, '')}
      />
    </div>
  );

  const sortByElem = (
    <div className="filter-values">
      <FormField
        type="select"
        name="sort-by"
        blockWrap={false}
        value={options[SEARCH_OPTIONS.SORT]}
        onChange={(e) => updateSearchOptions(SEARCH_OPTIONS.SORT, e.target.value)}
      >
        {OBJ_TO_OPTION_ELEM(SORT_BY)}
      </FormField>
    </div>
  );

  const uploadDateLabel =
    options[SEARCH_OPTIONS.CLAIM_TYPE] === SEARCH_OPTIONS.INCLUDE_CHANNELS ? __('Creation Date') : __('Upload Date');

  return (
    <div>
      <Button
        button="alt"
        label={__('Filter')}
        icon={ICONS.FILTER}
        iconRight={expanded ? ICONS.UP : ICONS.DOWN}
        onClick={toggleSearchExpanded}
      />
      <Form
        className={classnames('search__options', {
          'search__options--expanded': expanded,
        })}
      >
        <table className="table table--condensed">
          <tbody>
            {addRow(__('Type'), typeElem)}
            {addRow(uploadDateLabel, uploadDateElem)}
            {addRow(__('Sort By'), sortByElem)}
            {addRow(__('Other Options'), otherOptionsElem)}
          </tbody>
        </table>
      </Form>
    </div>
  );
};

export default SearchOptions;