import React, {Component} from 'react'
import styled from 'styled-components'
import {connect} from 'react-redux'
import {MdFlag, MdPhone, MdEmail, MdPerson, MdBusiness} from 'react-icons/lib/md'
import {browserHistory} from 'react-router'
import LastConnection from 'components/icons/last_connection'
import ProfileImage from 'components/profile_image'
import TimeAgo from 'components/utils/time_ago'
import Percentage from 'components/utils/percentage'
import Tag from 'components/utils/tag'
import FilterableList from 'components/filterable_list/filterable_list'
import {get_filter_on_click} from 'components/filterable_list/make_filter_maker_from_field'
import {FilterContent, FilterInput} from 'components/filterable_list/shared'
import persistent_state from 'common/persistent_state'
import {make_user_statuses, new_users_fuse} from 'common/users'
import auto_bind from 'common/auto_bind'
import {link, color} from 'common/styles'
import {
  property_getter, distance, set_from_array, set_count, set_intersection, array_from_set,
} from 'common/utilities'
import moment from 'common/moment'
import {get_user_workplaces_count} from 'selectors/user_missions'
import {get_workplaces} from 'selectors/workplaces'

function make_sort_by_distance(setState) {
  return (place) => get_filter_on_click(`place_${place.latitude}_${place.longitude}`, setState, (item) => {
    const user_distance = distance(item, place)
    if (user_distance === null) {
      return 1e9
    } else {
      return user_distance
    }
  })
}

class UsersList extends Component {
  constructor(props) {
    super(props)
    this.state = persistent_state.get(props.persistent_state_key, {
      ...FilterableList.initial_state,
      exclusive_filters: {
        status: {
          'mail': true,
          'active': true,
        },
      },
      order_by({last_connection}) {
        return last_connection ? -moment(last_connection).valueOf() : 0
      },
      workplace: props.workplace,
      radius_filter: null,
    })
    auto_bind(this)
  }

  static defaultProps = {
    users: [],
    fields: [],
    clickable: true,
    innerRef() {},
  }

  componentDidMount() {
    this.props.innerRef(this)
  }

  componentWillUnmount() {
    persistent_state.store(this.props.persistent_state_key, this.state)
  }

  set_state(arg) {
    this.setState(arg)
  }

  order_by_distance() {
    make_sort_by_distance(this.set_state)(this.state.workplace)()
  }

  get_selected_count(selected_user_ids) {
    return set_count(set_intersection(selected_user_ids, set_from_array(this.props.users.map(property_getter('id')))))
  }

  get_status_filter_maker() {
    return FilterableList.make_filter_maker_from_field({
      id: 'status',
      name: 'Statut',
      category: 'exclusive',
      value_ids: ['active', 'mail', 'rejected', 'inactive', 'blacklisted', 'invited', 'new'],
      get_value_props(status, selected = false) {
        const {name, icon} = make_user_statuses(selected ? 'white' : color('black', 'light'))[status]
        return {
          id: status,
          name: (
            <Tag icon={icon}>
              {name}
            </Tag>
          ),
        }
      },
      get_item_values({status: {status}}) {
        return [status]
      },
    })
  }

  get_missions_count_sort_maker() {
    return FilterableList.make_sort_maker({
      id: 'missions_count',
      name: (
        <Tag icon={<MdFlag />}>
          Missions réalisées
        </Tag>
      ),
      compare_with: ({missions_count}) => -missions_count,
    })
  }

  get_profile_rate_sort_maker() {
    return FilterableList.make_sort_maker({
      id: 'profile_rate',
      name: (
        <Tag icon={<MdPerson />}>
          Remplissage du profil
        </Tag>
      ),
      compare_with: ({profile_rate}) => -profile_rate,
    })
  }

  get_place_filter_maker() {
    return {
      keep_item(item, {workplace, radius_filter}) {
        return !workplace || !radius_filter || distance(item, workplace) < radius_filter * 1000
      },
      make_filter_props({setState, state: {workplace, radius_filter}}) {
        const sort_by_distance = make_sort_by_distance(setState)
        return {
          id: 'place',
          name: 'Distance',
          content: (
            <PlaceFilter
              place={workplace}
              radius_filter={radius_filter}
              setState={setState}
              sort_by_distance={sort_by_distance}
            />
          ),
          onClick: workplace && sort_by_distance(workplace)
        }
      }
    }
  }

  get_workplace_filter_maker() {
    const {workplaces, user_workplaces_count} = this.props
    return FilterableList.make_filter_maker_from_field({
      id: 'workplaces',
      name: 'Lieux où le candidat a travaillé',
      category: 'exclusive',
      tolerant: true,
      value_ids: Object.keys(workplaces),
      get_value_props(workplace_id) {
        return workplaces[workplace_id] || {}
      },
      get_item_values({id}) {
        return array_from_set(user_workplaces_count[id])
      },
    })
  }

  get_filters_and_users() {
    const {users, fields} = this.props
    const name_filter_maker = FilterableList.make_name_filter_maker('full_name')
    const filter_makers = [
      this.get_status_filter_maker(),
      name_filter_maker,
      this.get_missions_count_sort_maker(),
      this.get_profile_rate_sort_maker(),
      this.get_place_filter_maker(),
      this.get_workplace_filter_maker(),
      ...fields.map(FilterableList.make_filter_maker_from_field).filter(Boolean)
    ]

    return {
      filters: FilterableList.get_filters(filter_makers, users, this.state, this.set_state),
      users: FilterableList.get_filtered_items(
        filter_makers,
        users,
        this.state,
      ),
      name_filter: name_filter_maker.make_filter(this.set_state, users, new_users_fuse),
    }
  }

  render_user(user) {
    const {clickable, user_workplaces_count} = this.props
    const {id, first_name, last_name, phone_number, postal_code, missions_count, profile_rate, last_connection, email} = user
    const {workplace} = this.state
    const user_distance = workplace && distance(user, workplace)
    return (
      <User onClick={clickable && !user.not_clickable ? () => browserHistory.push(`/users/${id}`) : null}>
        <ProfileImage large {...user} />
        <Information>
          <Top>
            <Name>
              {last_name} {first_name}
            </Name>
            <Statistics>
              {[
                workplace ? {value: user_workplaces_count[id][workplace.id] || 0, icon: <MdBusiness />} : null,
                {value: missions_count, icon: <MdFlag />},
                {value: <Percentage>{profile_rate}</Percentage>, icon: <MdPerson />},
                last_connection ? {value: <TimeAgo>{last_connection}</TimeAgo>, icon: <LastConnection />} : null,
              ].filter(Boolean).map(({value, icon}, index) => (
                <Statistic key={index}>
                  {value}
                  <StatisticIcon>
                    {icon}
                  </StatisticIcon>
                </Statistic>
              ))}
            </Statistics>
          </Top>
          <Bottom>
            <Contacts>
              {[
                {icon: <MdPhone />, value: phone_number},
                {icon: <MdEmail />, value: email},
              ].map(({icon, value}, index) => value ? (
                <Contact key={index}>
                  <ContactIcon>
                    {icon}
                  </ContactIcon>
                  {value}
                </Contact>
              ) : null)}
            </Contacts>
            <Location>
              {workplace && user_distance !== null ? `${(user_distance / 1000).toFixed(1)} km` : postal_code}
            </Location>
          </Bottom>
        </Information>
      </User>
    )
  }

  render() {
    const {secondary_actions, main_action, selectable} = this.props
    const {filters, users, name_filter} = this.get_filters_and_users()
    return (
      <FilterableList
        icon={MdPerson}
        empty_text={"Aucun candidat"}
        filters={filters}
        name_filter={name_filter}
        secondary_actions={secondary_actions}
        main_action={main_action}
        render_item={this.render_user}
        get_selected_count={this.get_selected_count}
        selectable={selectable}
      >
        {users}
      </FilterableList>
    )
  }
}

const PlaceFilter = ({place, radius_filter, setState, sort_by_distance}) => {
  function on_place_select({label: address, location: {lat: latitude, lng: longitude}}) {
    const place = {address, latitude, longitude}
    setState({place})
    sort_by_distance(place)()
  }
  function on_clear_place_input() {
    setState({place: null})
  }
  function on_radius_change(radius_filter) {
    setState({radius_filter})
  }
  return (
    <FilterContent>
      <FilterInput
        label="Trier en fonction de la distance à"
        type='place'
        on_place_select={on_place_select}
        on_clear_place_input={on_clear_place_input}
        initial_query={(place && place.address) || ""}
      />
      <FilterInput
        label="Filtrer les candidats au delà de (km)"
        value={radius_filter || ""}
        onChange={on_radius_change}
      />
    </FilterContent>
  )
}

export default connect(
  (state) => ({
    workplaces: get_workplaces(state),
    user_workplaces_count: get_user_workplaces_count(state),
  })
)(UsersList)

const User = styled.div`
  flex: 1;
  ${({onClick}) => onClick ? link : ''}
  display: flex;
  align-items: center;
  padding-right: 5px;
`
const Information = styled.div`
  flex: 1;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  flex-direction: column;
  margin-left: 10px;
  height: 50px;
`
const Top = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
`
const Name = styled.div`
  font-size: 18px;
`
const Statistics = styled.div`
  display: flex;
  align-items: center;
`
const Statistic = styled.div`
  display: flex;
  align-items: center;
  margin-left: 10px;
`
const StatisticIcon = styled.div`
  margin-left: 3px;
  font-size: 16px;
`
const Bottom = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
`
const Contacts = styled.div`
  display: flex;
  align-items: center;
`
const Contact = styled.div`
  display: flex;
  margin-right: 10px;
`
const ContactIcon = styled.div`
  margin-right: 5px;
`
const Location = styled.div``
const Status = styled.div`
  display: flex;
  align-items: center;
`
const StatusIcon = styled.div`
  padding: 5px;
  font-size: 16px;
`
