import React, {Component} from 'react'
import {connect} from 'react-redux'
import classNames from 'classnames/bind'
import Calendar from 'components/generic_calendar'
import Tabbar from 'components/tabbar'
import Button from 'components/utils/button'
import TimePickers, {
  chunks_count_in_hour, chunk_length_in_minutes, chunks_count_in_day, get_periods, get_start_end,
  get_days_chunks, day_id,
} from 'components/input_calendar/time_pickers'
import moment from 'common/moment'
import {
  for_all, array_from_hash, range, array_from_set, group_consecutive, set_from_array, exist,
  empty_set, map_hash, create_hash,
} from 'common/utilities'
import {color} from 'common/constants'
import auto_bind from 'common/auto_bind'
import store from 'common/store'
import {dismiss_popover} from 'actions/display'
import {remove_item, create_item, toggle_item_id} from 'reducers/base'
import {tolerant_equal} from 'selectors/base'

const cx = classNames.bind(require('styles/mission_period_picker.scss'))

class MissionPeriodPicker extends Component {
  constructor(props) {
    super(props)
    auto_bind(this)
    this.update_initial_days(props.initial_events)
    let mode = "all"
    let identical_days = (day1, day2) => tolerant_equal(array_from_set(day1).sort(), array_from_set(day2).sort())
    if (empty_set(this.initial_days) || group_consecutive(array_from_hash(this.initial_days), identical_days).length == 1) {
      mode = "day"
    }
    this.state = {
      active_days: map_hash(this.initial_days, () => true),
      day_active: set_from_array(range(chunks_count_in_day).filter(
        (chunk) => exist(array_from_hash(this.initial_days), (day) => day[chunk])
      )),
      chunks: this.initial_days,
      mode,
    }
    this.all_time_pickers = {}
  }

  on_day_click(date) {
    this.setState(toggle_item_id(this.state, "active_days", day_id(date)))
  }

  on_create_period(start, end, paint) {
    let day_ids = [], current = moment(start)
    while (current.isBefore(end)) {
      day_ids.push(day_id(current))
      current.add(1, 'day')
    }
    this.setState({active_days: {
      ...this.state.active_days,
      ...map_hash(set_from_array(day_ids), () => paint)
    }})
  }

  flip(date, chunks, paint) {
    let chunks_range = create_hash(chunks, () => paint)
    switch (this.state.mode) {
      case "day":
        this.setState(({day_active}) => ({
          day_active: {
            ...day_active,
            ...chunks_range,
          },
        }))
        break
      case "all":
        let id = day_id(date)
        this.setState(({chunks, day_active}) => ({
          chunks: {
            ...chunks,
            [id]: {
              ...(chunks[id] || day_active),
              ...chunks_range,
            },
          },
        }))
        break
    }
  }

  update_initial_days(events) {
    this.initial_days = get_days_chunks(events)
  }

  get_day_events() {
    return array_from_set(this.state.active_days).map((day) => ({
      start: moment(day),
      end: moment(day).endOf('day'),
      full_days: true,
    }))
  }

  get_events() {
    let days = array_from_set(this.state.active_days)
    let events = []
    let add_events = (day, active_chunks) => {
      get_periods(active_chunks).forEach(({start, end}) => {
        events.push({
          ...get_start_end(day, start, end),
          full_days: false,
        })
      })
    }
    switch (this.state.mode) {
      case 'day':
        days.forEach((day) => add_events(day, this.state.day_active))
        break
      case 'all':
        days.forEach((day) => add_events(
          day,
          this.state.chunks[day] || this.state.day_active,
        ))
        break
    }
    if (events.length == 0) {
      events = days.map((day) => ({
        start: moment(day),
        end: moment(day).endOf('day'),
        full_days: true,
      }))
    }
    return events
  }

  on_save() {
    this.props.on_save(this.get_events())
  }

  render_time_picker() {
    let common_props = {
      drag_color: color('primary', 'light'),
      flip: this.flip,
    }
    switch (this.state.mode) {
      case "day":
        return (
          <TimePickers
            day_label={false}
            days={[{date: moment(), chunks: this.state.day_active}]}
            {...common_props}
            />
        )
      case "all":
        return (
          <TimePickers
            days={array_from_set(this.state.active_days).map((day) => moment(day)).sort((a, b) => a.isAfter(b) ? 1 : (a.isSame(b) ? 0 : -1)).map((day) => ({
              date: day,
              chunks: this.state.chunks[day_id(day)] || this.state.day_active,
            }))}
            {...common_props}
            />
        )
    }
  }

  set_mode(mode) {
    this.setState({mode})
  }

  render() {
    return (
      <div style={{display: 'flex', alignItems: 'stretch'}}>
        <div className={cx('mission-period-picker')}>
          <div className={cx('mission-period-picker__calendar')}>
            <Calendar
              hide_navigation
              events={{[color('primary')]: this.get_day_events()}}
              on_click={this.on_day_click}
              drag_color={color('primary')}
              on_drag_and_drop={this.on_create_period}
              />
          </div>
          <div className={cx('mission-period-picker__time')}>
            <Tabbar
              tabs={[
                {
                  label: "Horaires uniques pour toute la mission",
                  onClick: () => this.set_mode("day"),
                  is_active: () => this.state.mode == "day",
                },
                {
                  label: "Jour par jour",
                  onClick: () => this.set_mode("all"),
                  is_active: () => this.state.mode == "all",
                },
              ]}
              />
            <div className={cx('mission-period-picker__time-pickers')}>
              {this.render_time_picker()}
            </div>
            <div className={cx('mission-period-picker__time-button')}>
              <Button onClick={this.on_save}>
                Enregistrer les dates de la mission
              </Button>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

MissionPeriodPicker.defaultProps = {
  initial_events: [],
  update_events: () => {},
}

export default connect(
  (state, {mission_id}) => ({
    initial_events: array_from_hash(state.missions.events)
      .filter(({calenderable_id, deleted_at}) => calenderable_id == mission_id && !deleted_at)
  }),
)(MissionPeriodPicker)
