import * as React from 'react';
import * as classNames from 'classnames';
import * as numeral from 'numeral';
import * as _isEmpty from 'lodash.isempty';
import {ChangeEvent, Component, HTMLProps, MouseEvent, ReactEventHandler, ReactNode, SFC} from 'react';
import {Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Icon} from './../';
import {SelectOption, ViewMode} from './models';
import {getIconName} from './utils/viewMode';

export interface HeaderProps {
  hideSearchByField: boolean;
  hideToggleFilterButton: boolean;
  hideViewModeButton: boolean;
  hideTotalInfo: boolean;
  mainButton: HTMLProps<HTMLAnchorElement>;
  noSearchBarCollapse: boolean;
  searchPropertyOptions: SelectOption[];
  searchPropertyValue: string;
  searchInputPlaceholder: string;
  searchTerm: string;
  total: number;
  viewMode: ViewMode;
  viewModeButtons: ViewMode[];
  viewModeCustomElement: ReactNode;
  onTypeSearchTerm: (term: string) => void;
  onChangeSearchProperty: (e: ChangeEvent<HTMLSelectElement>) => void;
  onChangeViewMode: (viewMode: ViewMode) => void;
  onClickToggleFiltersButton: (e: MouseEvent<HTMLButtonElement>) => void;
}

export interface State {
  showSearchInput: boolean;
  viewModeMenuActive: boolean;
}

export class DatagridHeader extends Component<HeaderProps, State> {
  private searchInput: HTMLInputElement;

  constructor(props: HeaderProps) {
    super(props);

    const {noSearchBarCollapse, viewMode} = props;

    this.state = {
      showSearchInput: noSearchBarCollapse,
      viewModeMenuActive: false,
    };
  }

  render() {
    const {
      hideSearchByField,
      hideToggleFilterButton,
      hideViewModeButton,
      hideTotalInfo,
      mainButton,
      noSearchBarCollapse,
      searchInputPlaceholder,
      searchPropertyOptions,
      searchPropertyValue,
      searchTerm,
      total,
      viewMode,
      viewModeCustomElement,
      onTypeSearchTerm,
      onChangeSearchProperty,
      onChangeViewMode,
      onClickToggleFiltersButton} = this.props;

    const {showSearchInput, viewModeMenuActive} = this.state;

    return (
      <div className="bkn-datagrid-header">
        <div className="bkn-datagrid-header-left">
          {this.renderMainButton()}

          <div
            className={classNames(
              'input-search',
              {searching: !_isEmpty(searchTerm)},
            )}
          >
            <div className="icon">
              <Icon className="search" name="search" onClick={this.handleSearchIconClick} />
              <Icon className="close" name="close" onClick={this.handleRemoveIconClick} />
            </div>
            <input
              className="form-control"
              placeholder={searchInputPlaceholder}
              ref={instance => this.searchInput = instance}
              type="search"
              value={searchTerm}
              onChange={this.handleSearchTermChange}
            />
          </div>

          {(!hideSearchByField && searchPropertyOptions.length !== 0) && (
            <div className="search-property-select hidden-sm-down">
              <small className="text-uppercase">By</small>
              <select
                className="form-control-sm custom-select"
                value={searchPropertyValue}
                onChange={onChangeSearchProperty}
              >
                {this.renderOptions()}
              </select>
            </div>
          )}

          {!noSearchBarCollapse && (
            <button
              className="btn btn-link btn-icon btn-square btn-sm hidden-lg-up"
              onClick={this.toggleHeaderRightContainer}
            >
              <Icon name="more" />
            </button>
          )}
        </div>

        <div
          className={classNames(
            'bkn-datagrid-header-right',
            {
              'sm-active': !showSearchInput,
              'no-main-button': !mainButton,
            },
          )}
        >
          {!hideTotalInfo && (
            <small className="text-uppercase hidden-xs-down">{numeral(total).format('0,0')} found</small>
          )}

          <button
            className="btn btn-link btn-icon btn-square hidden-lg-up"
            onClick={this.toggleHeaderRightContainer}
          >
            <Icon name="search" />
          </button>

          {viewModeCustomElement || !hideViewModeButton && (
            <Dropdown
              className="view-mode-menu"
              isOpen={viewModeMenuActive}
              toggle={this.toggleViewModeMenu}
            >
              <DropdownToggle
                className="btn-link btn-icon btn-square"
                id="view-mode-menu"
                data-toggle="dropdown"
                aria-haspopup
                aria-expanded={false}
              >
                {viewMode === ViewMode.Table && <Icon name={getIconName(viewMode)} />}
                {viewMode === ViewMode.Cards && <Icon name={getIconName(viewMode)} />}
                {viewMode === ViewMode.Map && <Icon name={getIconName(viewMode)} />}
              </DropdownToggle>

              <DropdownMenu
                right
                aria-labelledby="view-mode-menu"
              >
                {this.renderViewModeButtons()}
              </DropdownMenu>
            </Dropdown>
          )}

          {!hideToggleFilterButton && (
            <button
              className="btn btn-link btn-icon btn-square"
              onClick={onClickToggleFiltersButton}
            >
              <Icon name="filter_list" />
            </button>
          )}
        </div>
      </div>
    );
  }

  renderMainButton() {
    const {mainButton} = this.props;

    if (!mainButton) {
      return null;
    }

    const {children, ...otherMainButtonProps} = mainButton;

    return (
      <a
        className="btn btn-primary btn-link btn-icon btn-square btn-list-action"
        {...otherMainButtonProps}
      >
        <Icon name="add" />
      </a>
    );
  }

  renderOptions = () => {
    const options = this.props.searchPropertyOptions;
    return options.map(o => <option key={o.value} value={o.value}>{o.text}</option>);
  }

  renderViewModeButtons = () => {
    const {viewMode, viewModeButtons} = this.props;

    return viewModeButtons
      .filter(button => button !== viewMode)
      .map(button => (
        <DropdownItem
          key={button}
          className="btn btn-link btn-icon btn-square"
          onClick={this.handleViewModeChange(button)}
        >
          <Icon name={getIconName(button)} />
        </DropdownItem>
      ));
  }

  handleViewModeChange = (viewMode: ViewMode) => () => {
    this.props.onChangeViewMode(viewMode);
    this.toggleViewModeMenu();
  }

  handleSearchTermChange = (e: ChangeEvent<HTMLInputElement>) => {
    this.props.onTypeSearchTerm(e.target.value);
  }

  handleRemoveIconClick = () => {
    this.props.onTypeSearchTerm('');
    this.searchInput.focus();
  }

  handleSearchIconClick = () => {
    this.searchInput.focus();
  }

  toggleHeaderRightContainer = () => {
    this.setState({showSearchInput: !this.state.showSearchInput});
  }

  toggleViewModeMenu = () => {
    this.setState({viewModeMenuActive: !this.state.viewModeMenuActive});
  };
}
