import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import moment from 'moment';
import { I18n as I18nDecorator } from '@procore/core-react';
import Calendar from '../Calendar/';
import baseStyles from './FilterCalendarWithPreMenu.scss';
import composeStyles from '../../../shared/stylesheetComposer';
import {
  getFormattedDates,
  getMomentDates,
  isDateValid,
  isValidcommittedDates
} from '../_shared/utils/dates';
import { FILTERS_ANALYTICS } from '../Filters';
import getProcoreLocale from '../_shared/utils/getProcoreLocale';

export class FilterCalendarWithPreMenu extends React.Component {
  static propTypes = {
    filter: PropTypes.shape({
      endpoint: PropTypes.string.isRequired,
      key: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired
    }).isRequired,
    I18n: PropTypes.shape().isRequired,
    options: PropTypes.shape(),
    onRemove: PropTypes.func.isRequired,
    onSave: PropTypes.func.isRequired,
    removeFilter: PropTypes.func.isRequired,
    selected: PropTypes.array.isRequired,
    isRangeToggleVisible: PropTypes.bool,
    isRange: PropTypes.bool,
    stylesheets: PropTypes.arrayOf(PropTypes.shape()),
    footer: PropTypes.oneOfType([PropTypes.node, PropTypes.element]),
    defaultSelectedDates: PropTypes.arrayOf(PropTypes.string)
  }

  static defaultProps = {
    isRangeToggleVisible: true,
    stylesheets: [],
    footer: null,
    defaultSelectedDates: [],
    options: {}
  };

  constructor(props) {
    super(props);
    this.styles = composeStyles(baseStyles, [...props.stylesheets]);

    const { selected } = props;
    const firstDate = moment(selected[0], 'YYYY-MM-DD HH:mm:ss Z');
    const isValidDate = firstDate._isValid;
    let committedDates = [];

    if (isValidDate) {
      committedDates = selected;
    }

    this.state = {
      preMenuExpanded: false,
      calendarIsExpanded: false,
      ignoreBlur: false,
      committedDates
    };
  }

  componentDidMount() {
    const { selected } = this.props;

    if (selected.length === 0) {
      this.togglePreMenu();
    }

    window.addEventListener('click', this.onBlur);
  }

  componentWillUnmount() {
    window.removeEventListener('click', this.onBlur);
  }


  onBlur = () => {
    const {
      calendarIsExpanded,
      ignoreBlur,
      preMenuExpanded
    } = this.state;

    if (ignoreBlur === true) {
      return;
    }

    const { selected } = this.props;
    const calendarIsOpen = (calendarIsExpanded && !preMenuExpanded);

    if (calendarIsOpen) {
      this.onBlurCalendar();
    } else {
      this.onBlurPreMenu();
    }
  }

  onBlurCalendar = () => {
    const { committedDates } = this.state;
    const {
      filter,
      onSave,
      options,
      removeFilter,
      selected
    } = this.props;

    const newState = {
      calendarIsExpanded: false
    };

    this.setState(newState, () => {
      if (isValidcommittedDates(committedDates)) {
        onSave(filter, committedDates, options);
      } else {
        removeFilter(filter.key);
      }
    });
  }

  onBlurPreMenu = () => {
    const {
      filter,
      removeFilter,
      selected
    } = this.props;

    const newState = {
      preMenuExpanded: false
    };

    this.setState(newState, () => {
      if (selected.length === 0) {
        removeFilter(filter.key);
      }
    });
  }

  onCalendarClick = (evt) => {
    evt.stopPropagation();
  }

  onListItemClick = (item) => {
    const {
      filter,
      onSave,
      options
    } = this.props;
    const selected = [item.key];

    if (item.type && item.type === 'calendar') {
      this.expandCalendar();
    } else {
      const newState = {
        committedDates: [],
        preMenuExpanded: false
      };

      this.setState(newState, () => {
        onSave(filter, selected, options);
      });
    }
  }

  onCalendarRangeChange = () => {
    this.setState({
      committedDates: []// clear dates when user toggles between single and date range
    });
  }

  updateCommittedDates = (nextCommittedUtcDates) => {
    this.setState({
      committedDates: nextCommittedUtcDates
    });
  }

  expandCalendar = () => {
    this.setState({
      ignoreBlur: true,
      calendarIsExpanded: true,
      preMenuExpanded: false
    });

    setTimeout(() => {
      this.setState({ ignoreBlur: false });
    }, 100);
  }

  togglePreMenu = () => {
    if (this.props.disabled) {
      return;
    }

    const {
      calendarIsExpanded,
      preMenuExpanded
    } = this.state;

    if (!calendarIsExpanded && !preMenuExpanded) {
      this.setState({
        ignoreBlur: true,
        preMenuExpanded: true
      });
    } else if (!calendarIsExpanded && preMenuExpanded) {
      this.setState({
        ignoreBlur: true,
        preMenuExpanded: false
      });
    } else if (calendarIsExpanded && !preMenuExpanded) {
      this.onBlurCalendar();
    }

    setTimeout(() => {
      this.setState({ ignoreBlur: false });
    }, 100);
  }

  render() {
    const {
      onRemove,
      filter,
      I18n: { locale },
      isRange,
      isRangeToggleVisible,
      defaultSelectedDates,
      selected
    } = this.props;
    const { type_options: { preMenu } } = filter;
    const {
      preMenuExpanded,
      calendarIsExpanded,
      committedDates
    } = this.state;
    const { styles } = this;

    const calendarLocale = getProcoreLocale(locale);
    const savedCommittedDates = committedDates.length
      ? getMomentDates(committedDates, calendarLocale)
      : getMomentDates(defaultSelectedDates, calendarLocale);
    const keyboardTempValues = getFormattedDates(savedCommittedDates);
    const currentMonth = isDateValid(savedCommittedDates, 0)
      ? moment(savedCommittedDates[0])
      : moment().locale(calendarLocale);

    const remove = (
      <button
        disabled={this.props.disabled}
        className={cx(styles.tokenRemove,
          {
            [styles.expanded]: (preMenuExpanded || calendarIsExpanded),
            [styles.disabled]: this.props.disabled
          })}
        data-key={filter.key}
        onClick={onRemove}
      />
    );

    const caret = (
      <div
        className={cx(styles.tokenCaret, { [styles.disabled]: this.props.disabled })}
      >
        <span
          className={cx(
            'fa',
            'fa-caret-down',
            styles.arrow,
            { [styles.expanded]: (preMenuExpanded || calendarIsExpanded) }
          )}
        />
      </div>
    );

    const renderHeading = () => {
      const { selected } = this.props;
      const {
        calendarIsExpanded,
        preMenuExpanded
      } = this.state;
      let selectedValue = '';

      const startDate = keyboardTempValues[0] ? keyboardTempValues[0] : '';
      const endDate = keyboardTempValues[1] ? (` - ${keyboardTempValues[1]}`) : '';
      const dateIsSelected = (startDate !== '' || endDate !== '');
      const islargeHeading = (selected.length === 0 && !calendarIsExpanded && preMenuExpanded);

      if (dateIsSelected) {
        selectedValue = `${startDate}${endDate}`;
      } else if (calendarIsExpanded && !preMenuExpanded) {
        const calendarPreMenuItem = preMenu.filter(item => item.type === 'calendar');

        selectedValue = (calendarPreMenuItem[0] && calendarPreMenuItem[0].value)
          ? calendarPreMenuItem[0].value
          : '';
      } else {
        const selectedPreMenuItem = preMenu.filter(item => item.key === selected[0]);

        selectedValue = (selectedPreMenuItem[0] && selectedPreMenuItem[0].value)
          ? selectedPreMenuItem[0].value
          : '';
      }

      return (
        <div className={cx(styles.tokenTitle, styles.checkbox, { [styles.disabled]: this.props.disabled })}>
          <div className={cx(styles['tokenTitle__date-title'], { [styles['tokenTitle__date-title--large']]: islargeHeading })}>{filter.value}</div>
          <div className={styles.tokenTitle__date}>{selectedValue}</div>
        </div>
      );
    };

    const isSelectedListItem = (key) => {
      let isValidDate = false;

      if (key === 'calendar') {
        const firstDate = moment(selected[0], 'YYYY-MM-DD HH:mm:ss Z');
        isValidDate = firstDate._isValid;
      }

      if ((selected[0] === key) || isValidDate) {
        return true;
      }

      return false;
    };

    return (
      <div className={styles.tokenContainerCalendar} >

        <div
          className={
            cx(styles.tokenHead, styles.filterCalendarHead,
              {
                [styles.expanded]: (preMenuExpanded || calendarIsExpanded),
                [styles.disabled]: this.props.disabled
              })
          }
          data-key={filter.key}
        >
          {remove}
          <div
            onClick={this.togglePreMenu}
            ref={(el) => { this.container = el; }}
          >
            {renderHeading()}
            {caret}
          </div>
        </div>

        <div ref={(el) => { this.body = el; }}>
          {preMenuExpanded &&
            <div className={cx(styles.tokenBody, { [styles.expanded]: preMenuExpanded })}>
              <ul className={styles.list}>
                {preMenu.map(item => (
                  <li
                    key={item.key}
                    className={cx(
                      styles.list__item,
                      { [styles['list__item--selected']]: isSelectedListItem(item.key) }
                    )}
                    onClick={() => this.onListItemClick(item)}
                  >{item.value}</li>
                ))}
              </ul>
            </div>
          }

          {calendarIsExpanded &&
            <div className={styles.tokenBodyCalendarWrap}>
              <div
                className={cx(styles.tokenBodyCalendar, { [styles.expanded]: calendarIsExpanded })}
                onClick={this.onCalendarClick}
              >
                <Calendar
                  committedDates={savedCommittedDates}
                  keyboardTempValues={keyboardTempValues}
                  currentMonth={currentMonth}
                  isRange={isRange}
                  isRangeToggleVisible={isRangeToggleVisible}
                  locale={calendarLocale}
                  onRangeChange={this.onCalendarRangeChange}
                  updateCommittedDates={this.updateCommittedDates}
                />
                {this.props.footer}
              </div>
            </div>
          }
        </div>

      </div>
    );
  }
}

export default I18nDecorator.withConsumer(FilterCalendarWithPreMenu);
