import {isUndefined, extend} from 'lodash'
import {DragDropMixin} from 'react-dnd'
import Promise from 'bluebird'
import React from 'react/addons'
import {Link} from 'react-router'
import humanize from 'humanize-plus'
import Immutable from 'immutable'

import add from 'sto-helpers/lib/add'
import countCredits from 'sto-helpers/lib/countCredits'
import semesterName from 'sto-helpers/lib/semesterName'
import {isCurrentSemester} from 'sto-helpers/lib/isCurrent'
import {Course, MissingCourse, EmptyCourseSlot} from './course'
import studentActions from '../flux/studentActions'
import itemTypes from '../models/itemTypes'

let cx = React.addons.classSet

let Semester = React.createClass({
	mixins: [DragDropMixin],

	propTypes: {
		student: React.PropTypes.object.isRequired,
		year: React.PropTypes.number.isRequired,
		semester: React.PropTypes.number.isRequired,
	},

	configureDragDrop(registerType) {
		registerType(itemTypes.COURSE, {
			dropTarget: {
				acceptDrop(courseIdentifier) {
					console.log('dropped courseIdentifier', courseIdentifier)
					let {clbid, fromSchedule} = courseIdentifier
					if (fromSchedule)
						studentActions.moveCourse(this.props.student.id, fromSchedule, this.state.schedule.id, clbid)
					else
						studentActions.addCourse(this.props.student.id, this.state.schedule.id, clbid)
				}
			}
		})
	},

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},

	componentWillReceiveProps(nextProps) {
		let activeSchedules = nextProps.student.activeSchedules
		let schedule = activeSchedules.find((s) => s.year === this.props.year && s.semester === this.props.semester)

		Promise.all([schedule.courses, schedule.validate()]).then((results) => {
			let [courses, validation] = results
			this.setState({
				schedule,
				courses: Immutable.List(courses),
				validation,
			})
		})
	},

	getInitialState() {
		return {
			courses: Immutable.List(),
			schedule: null,
			validation: {},
		}
	},

	render() {
		// console.log('semester render', this.state.schedule)

		let infoIcons = []
		if (this.state.schedule && this.state.courses.size) {
			let courseCount = this.state.courses.size
			infoIcons.push(React.createElement('li',
				{className: 'semester-course-count', key: 'course-count'},
				`${courseCount} ${humanize.pluralize(courseCount, 'course')}`))

			let credits = this.state.courses
				.filterNot(isUndefined) // remove any undefined items
				.map(c => c.credits)
				.reduce(add)

			if (credits) {
				infoIcons.push(React.createElement('li',
					{className: 'semester-credit-count', key: 'credit-count'},
					`${credits} ${humanize.pluralize(credits, 'credit')}`))
			}
		}
		let infoBar = React.createElement('ul', {className: 'info-bar'}, infoIcons)

		let courseList = null
		if (this.state.schedule && this.state.courses) {
			let courseObjects = this.state.courses
				.filterNot(isUndefined)
				.map((course, i) =>
					React.createElement(Course, {
						key: `${course.clbid}-${i}`,
						info: course,
						student: this.props.student,
						schedule: this.state.schedule,
						index: i,
						conflicts: this.state.validation.conflicts,
					}))

			let couldntFindSlots = this.state.courses
				.filter(isUndefined) // only keep the undefined items
				.map((c, i) => React.createElement(MissingCourse, {key: i}))

			// maxCredits is 4 for fall/spring and 1 for everything else
			let maxCredits = ([1, 3].indexOf(this.props.semester) !== -1) ? 4 : 1
			let currentCredits = countCredits(this.state.courses.toArray())

			let emptySlots = []
			if (currentCredits < maxCredits) {
				emptySlots =
					Immutable.Range(Math.floor(currentCredits), maxCredits)
					.skip(couldntFindSlots.size)
					.map((i) => React.createElement(EmptyCourseSlot, {key: `empty-${i}`}))
			}

			let courseBlocks = courseObjects
				.concat(couldntFindSlots)
				.concat(emptySlots)
				.toJS()

			courseList = React.createElement('div',
				{className: 'course-list'},
				courseBlocks)
		}
		else if (this.state.schedule) {
			courseList = React.createElement('div', {className: 'loading'}, 'Loading Courses')
		}

		let droppableIsMoving = this.getDropState(itemTypes.COURSE).isDragging
		let droppableIsOver = this.getDropState(itemTypes.COURSE).isHovering

		let semesterProps = {
			className: cx({
				semester: true,
				invalid: this.state.validation.hasConflict,
				'can-drop': droppableIsMoving,
				'is-over': droppableIsOver,
			})
		}

		return React.createElement('div',
			extend(semesterProps, this.dropTargetFor(itemTypes.COURSE)),
			React.createElement('header', {className: 'semester-title'},
				React.createElement('h1', null, React.createElement(Link,
					{
						to: 'semester',
						params: {
							id: this.props.student.id,
							year: this.props.year,
							semester: this.props.semester,
						},
					},
					semesterName(this.props.semester))),
				infoBar,
				React.createElement('button', {
					className: 'remove-semester',
					title: `Remove ${this.props.year} ${semesterName(this.props.semester)}`,
					onClick: this.removeSemester,
				})),
			courseList)
	},

	removeSemester() {
		let {year, semester} = this.props
		let currentTermSchedules = this.props.student.schedules.filter(isCurrentSemester(year, semester))

		let scheduleIds = currentTermSchedules.map(s => s.id)

		studentActions.destroyMultipleSchedules(this.props.student.id, scheduleIds)
	},
})

export default Semester

@@ -1742,42 +1742,8 @@
 lts%0A
-%09%09%09this.setState(%7B%0A%09%09%09%09schedule,%0A%09
 %09%09%09c
@@ -1740,33 +1740,34 @@
 sults%0A%09%09%09courses
-:
+ =
  Immutable.List(
@@ -1774,22 +1774,54 @@
 courses)
-,%0A%09%09%09%09
+%0A%09%09%09this.setState(%7Bschedule, courses, 
 validati
@@ -1822,21 +1822,16 @@
 lidation
-,%0A%09%09%09
 %7D)%0A%09%09%7D)%0A

Tweak semester.setState