import React, { Component } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash.omit';
import classNames from 'classnames';
import { DateRangePicker } from 'react-dates';
import 'react-dates/lib/css/_datepicker.css';

import '../base';
import styles from './DatepickerRange.styl';
import Label from './Label';
import newId from '../utils/newId';

const START_DATE = 'startDate';
const END_DATE = 'endDate';

export default class DatepickerRange extends Component {
  constructor(props) {
    super(props);

    let focusedInput = null;
    if (props.autoFocus) {
      focusedInput = START_DATE;
    } else if (props.autoFocusEndDate) {
      focusedInput = END_DATE;
    }

    this.state = {
      focusedInput,
      startDate: props.startDate || null,
      endDate: props.endDate || null
    };

    this.onDatesChange = this.onDatesChange.bind(this);
    this.onFocusChange = this.onFocusChange.bind(this);
    this.disableReadonly = this.disableReadonly.bind(this);
  }

  componentWillMount() {
    this.startDateId = newId();
    this.endDateId = newId();
  }

  componentDidMount() {
    // this is a hack to get a readonly input field
    document.getElementById(this.startDateId).readOnly = true;
    document.getElementById(this.endDateId).readOnly = true;
  }

  // in case props are changing, update the state
  componentWillReceiveProps(nextProps) {
    const { startDate, endDate } = nextProps;
    this.setState({
      startDate: startDate || null,
      endDate: endDate || null
    });
  }

  onDatesChange({ startDate, endDate }) {
    this.setState({ startDate, endDate }, () => {
      this.disableReadonly();

      // // fire change event in case the datepicker has been closed
      if (this.state.focusedInput === null) {
        this.props.onDatesChange({ startDate, endDate });
      }
    });
  }

  onFocusChange(newFocusedInput) {
    const { focusedInput, startDate, endDate } = this.state;

    // set state before updating the store which might cause a reload of the page and setState on an umounted component will throw an error
    this.setState({ focusedInput: newFocusedInput }, () => {
      this.disableReadonly();

      // fire the change event in case we close the datepicker after selecting only a single date
      if (
        (focusedInput === START_DATE || focusedInput === END_DATE) &&
        newFocusedInput === null
      ) {
        // here we access the internal saved properties startDate and endDate
        this.props.onDatesChange({ startDate, endDate });
      }
    });
  }

  disableReadonly() {
    const { enforceReadonly, readonly, toggleReadonly } = this.props;
    if (!enforceReadonly && readonly && toggleReadonly) {
      toggleReadonly();
    }
  }

  render() {
    const { focusedInput, startDate, endDate } = this.state;
    const {
      name,
      label,

      error,
      success,
      warning,
      info,

      readonly,
      enforceReadonly
    } = this.props;

    const wrapperClasses = classNames({
      [styles.wrapper]: true,
      [styles.readonly]: readonly,
      [styles.enforceReadonly]: enforceReadonly,
      [styles.error]: !!error,
      [styles.warning]: !!warning,
      [styles.info]: !!info,
      [styles.success]: !!success,
      [styles.labelOffset]: label
    });

    return (
      <div className={wrapperClasses}>
        {!!label && (
          <Label
            style={{ marginTop: '0px', marginBottom: '10px' }}
            htmlFor={name}
            {...{ error, warning, info, success }}
          >
            {label}
          </Label>
        )}
        <DateRangePicker
          {...omit(this.props, [
            'input',
            'meta',
            'label',
            'timezone',
            'readonly',
            'enforceReadonly',
            'toggleReadonly',
            'error',
            'warning',
            'info',
            'success',
            'value',
            'onChange',
            'paramStartDate',
            'paramEndDate',
            'applyOnBlur'
          ])}
          startDateId={this.startDateId}
          endDateId={this.endDateId}
          startDate={startDate}
          endDate={endDate}
          focusedInput={focusedInput}
          onDatesChange={this.onDatesChange}
          onFocusChange={this.onFocusChange}
        />
      </div>
    );
  }
}

DatepickerRange.defaultProps = {
  displayFormat: 'DD.MM.YYYY',
  showClearDates: true
};

DatepickerRange.propTypes = {
  displayFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  showClearDates: PropTypes.bool,
  startDate: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.string
  ]),
  endDate: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.string
  ]),
  onDatesChange: PropTypes.func,
  label: PropTypes.string,
  error: PropTypes.string,
  warning: PropTypes.bool,
  info: PropTypes.bool,
  success: PropTypes.bool,
  readonly: PropTypes.bool,
  enforceReadonly: PropTypes.bool,
  toggleReadonly: PropTypes.func
};

DatepickerRange.defaultProps = {
  startDate: undefined,
  endDate: undefined,
  onDatesChange: undefined,
  label: undefined,
  error: undefined,
  warning: undefined,
  info: undefined,
  success: undefined,
  readonly: undefined,
  enforceReadonly: undefined,
  toggleReadonly: undefined
};
