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 './FilterCalendar.scss';
import composeStyles from '../../../shared/stylesheetComposer';
import {
  getFormattedDates,
  getMomentDates,
  isDateValid,
  isValidcommittedDates
} from '../_shared/utils/dates';
import getProcoreLocale from '../_shared/utils/getProcoreLocale';

import { FILTERS_ANALYTICS } from '../Filters';

export class FilterCalendar 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,
    committedDates: 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),
    disabled: PropTypes.bool,
  }

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

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

    this.state = {
      expanded: false,
      ignoreBlur: false,
      committedDates: props.committedDates
    };
  }

  componentDidMount() {
    const { committedDates } = this.state;
    const commitedStartDate = committedDates[0] ? committedDates[0] : null;

    // If there's no date/s selected on instantiation, it's a new filter. Expand and load.
    if (!commitedStartDate) {
      this.expandCalendar();
    }

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

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

  onBlur = () => {
    const {
      ignoreBlur,
      committedDates
    } = this.state;
    const { filter, options } = this.props;

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

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

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

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

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

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

    const { committedDates, isRange } = this.props;
    const { expanded } = this.state;
    const commitedStartDate = committedDates[0] ? committedDates[0] : null;
    const commitedEndDate = committedDates[1] ? committedDates[1] : null;

    if ((isRange && commitedStartDate && commitedEndDate) || (!isRange && commitedStartDate)) {
      this.setState({
        ignoreBlur: true,
        expanded: !expanded
      });

      // save when calender is closed
      if (expanded) {
        this.onBlur();
      }

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

  expandCalendar = () => {
    this.setState({
      ignoreBlur: true,
      expanded: true
    });

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

  render() {
    const {
      onRemove,
      filter,
      I18n: { locale },
      isRange,
      isRangeToggleVisible,
      defaultSelectedDates
    } = this.props;
    const { expanded, 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]: expanded, [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]: this.state.expanded }
          )}
        />
      </div>
    );

    const startDate = keyboardTempValues[0] ? keyboardTempValues[0] : '';
    const endDate = keyboardTempValues[1] ? (` - ${keyboardTempValues[1]}`) : '';
    const noDatesSelected = (startDate === '' && endDate === '');

    const heading = (
      <div className={cx(styles.tokenTitle, styles.checkbox, { [styles.disabled]: this.props.disabled })}>
        <div className={cx(styles['tokenTitle__date-title'], { [styles['tokenTitle__date-title--large']]: noDatesSelected })}>{filter.value}</div>
        <div className={styles.tokenTitle__date}>{startDate}{endDate}</div>
      </div>
    );

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

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

        <div
          className={styles.tokenBodyCalendarWrap}
          ref={(el) => { this.body = el; }}
        >
          <div
            className={cx(styles.tokenBodyCalendar,
              { [styles.expanded]: expanded })}
            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>
    );
  }
}

export default I18nDecorator.withConsumer(FilterCalendar);
