import throttle from './throttle'
import Vector from 'vector'
import store from 'store'

export default class {
	constructor() {
		this.checkKeyThrottled = throttle(() => this.checkKey(), 100)
		this.checkKeyDownThrottled = throttle(() => this.checkKeyDown(), 50)
		this.moveThrottled = throttle(() => this.move())
	}

	update() {
		this.checkKeyRotate()
		return this.checkKeyDownThrottled()
			|| this.checkKeyThrottled()
			|| this.moveThrottled(500 / store.options.current.speed)
	}

	move() {
		const segments = store.options.objects.shape.segments
		const field = store.options.objects.field

		const down = new Vector(0, 1)
		const newSegments = segments.map(segment => Vector.add(segment, down))

		if (this.checkCollision(newSegments)) {
			segments.forEach(segment => field[segment.y][segment.x] = 1)
			return 1
		}

		this.setNewPosition(newSegments)
		return 0
	}

	checkKey() {
		const keys = store.keyboard.downActions
		const direction = new Vector()

		const segments = store.options.objects.shape.segments

		if (keys.right()) direction.addXY(1, 0)
		if (keys.left()) direction.addXY(-1, 0)

		if (!direction.isEmpty()) {
			const newSegments = segments.map(segment => Vector.add(segment, direction))
			if (!this.checkCollision(newSegments)) {
				this.setNewPosition(newSegments)
				return
			}
		}
	}

	checkKeyDown() {
		if (store.keyboard.downActions.down()) {
			return this.moveThrottled(0)
		}
	}

	checkKeyRotate() {
		if (store.keyboard.pressedActions.up()) {
			const segments = store.options.objects.shape.segments
			const newShape = this.rotateShape(segments)
			if (!this.checkCollision(newShape)) {
				this.setNewPosition(newShape)
			}
		}
	}

	checkCollision(segments) {
		const [width, height] = store.options.dimensions.toArray()
		const field = store.options.objects.field

		return segments.some(({ x, y }) => {
			return x < 0 || y < 0 ||
				x >= width || y >= height ||
				field[y][x] > 0
		})
	}


	rotateShape(segments) {
		const center = segments
			.reduce((acc, item) => acc.add(item), new Vector())
			.divide(segments.length)
			.round()
		const deg90 = -Math.PI / 2
		const rotate = segment => Vector.subtract(segment, center).rotate(deg90).add(center)
		return segments.map(rotate)
	}

	setNewPosition(newShape) {
		const segments = store.options.objects.shape.segments
		segments.forEach((segment, i) => segment.copy(newShape[i]))
	}

	makeShape() {
		const { shape, snake, apple } = store.options.objects

		shape.segments = [
			apple,
			...snake.segments
		]

		snake.segments.forEach((segment, i) => {
			shape.segments[i + 1].copy(segment)
		})
	}
}
