import Unit from '../unit';
import SpriteItem from '../sprite-item';
import SpriteCharacter from './sprite';
import Interval from '../interval';

const MONSTER_TYPE = {
	ZOMBIE: 'ZOMBIE',
	GOBLIN: 'GOBLIN',
	IMP: 'IMP',
	SKELET: 'SKELET',
	MUDDY: 'MUDDY',
	SWAMPY: 'SWAMPY',
	BOSS: 'BOSS',
};

const monsters = {
	[MONSTER_TYPE.ZOMBIE]: { w: 16, h: 16, speed: 0.008, health: 1, power: 1 },
	[MONSTER_TYPE.GOBLIN]: { w: 16, h: 16, speed: 0.009, health: 2, power: 2 },
	[MONSTER_TYPE.IMP]: { w: 16, h: 16, speed: 0.018, health: 1, power: 1 },
	[MONSTER_TYPE.SKELET]: { w: 16, h: 16, speed: 0.015, health: 4, power: 2 },
	[MONSTER_TYPE.MUDDY]: { w: 16, h: 16, speed: 0.008, health: 6, power: 3 },
	[MONSTER_TYPE.SWAMPY]: { w: 16, h: 16, speed: 0.009, health: 10, power: 4 },
	[MONSTER_TYPE.BOSS]: { w: 32, h: 36, speed: 0.02, health: 20, power: 6 },
};

class Generator {
	private bodies: Record<string, SpriteCharacter> = {};

	private intervals: Record<string, Interval> = {};

	get types() {
		return MONSTER_TYPE;
	}

	reset() {
		this.intervals = {
			[MONSTER_TYPE.ZOMBIE]: new Interval(1_000),
			[MONSTER_TYPE.IMP]: new Interval(5_000),
			[MONSTER_TYPE.GOBLIN]: new Interval(8_000),
			[MONSTER_TYPE.SKELET]: new Interval(20_000),
			[MONSTER_TYPE.MUDDY]: new Interval(25_000),
			[MONSTER_TYPE.SWAMPY]: new Interval(45_000),
			[MONSTER_TYPE.BOSS]: new Interval(100_000),
		};
	}

	constructor(image: HTMLImageElement) {
		this.bodies[MONSTER_TYPE.ZOMBIE] = new SpriteCharacter(
			new SpriteItem(image, 368, 16, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.GOBLIN] = new SpriteCharacter(
			new SpriteItem(image, 368, 32, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.IMP] = new SpriteCharacter(
			new SpriteItem(image, 368, 48, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.SKELET] = new SpriteCharacter(
			new SpriteItem(image, 368, 80, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.MUDDY] = new SpriteCharacter(
			new SpriteItem(image, 368, 112, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.SWAMPY] = new SpriteCharacter(
			new SpriteItem(image, 432, 112, 16, 16, 4),
		);
		this.bodies[MONSTER_TYPE.BOSS] = new SpriteCharacter(
			new SpriteItem(image, 16, 364, 32, 36, 4),
		);

		this.reset();
	}

	make(dt: number) {
		return Object.keys(this.intervals).reduce<Unit[]>((acc, type) => {
			const interval = this.intervals[type];
			if (interval.next(dt)) {
				interval.decrease(10);
				acc.push(
					new Unit({
						x: 0,
						y: 0,
						...monsters[type],
						body: this.bodies[type],
					}),
				);
			}

			return acc;
		}, []);
	}

	updateBodies(dt: number) {
		Object.values(this.bodies).forEach((body) => body.update(dt));
	}
}

export default Generator;
