
---- The evil Crysts ----
-------------------------------------------------------------------------------

Cryst = {
	x = 0, y = 0, scale = 1.0, rot = 0.0,
	width = 64, height = 64,
	dir = {0, 0}, dirchange = 0,
	color = colors.white, dead = false,
	image = nil,
	nuketimer = 0
}

function Cryst:new(c)
	local oc = c
	c = c or {}
	setmetatable(c, self)
	self.__index = self
	if not oc then c:randomize() end
	table.insert(Crysts.list, c)
	return c
end

function Cryst:newBoss()
	local c = self:new()
	c.width, c.height = c.width * 2, c.height * 2
	c.dir[1] = c.dir[1] * 2
	c.x = math.random(S_BORDER + 5, SCREEN_WIDTH - S_BORDER - c.width - 5)
	c.y = math.random(S_BORDER + 5, SCREEN_HEIGHT - S_BORDER - c.height - 5)
	c.image = imgs.crystboss
	c.boss = true
	return c
end

function Cryst:randomize()
	self.scale = math.random(Level.minCrystSize, Level.maxCrystSize)/100
	self.rot = math.rad(math.random(0, 360))
	self.width = self.width * self.scale
	self.height = self.height * self.scale
	self.dir = { math.rad(math.random(0, 360)), math.random(5, 12)/10*Level.crystSpeedFactor }
	self.dirchange = math.random(-0.06, 0.06)
	self.color = Color.new(150 + math.random(110), math.random(110), math.random(110))
	self.x = math.random(S_BORDER + 5, SCREEN_WIDTH - S_BORDER - self.width - 5)
	self.y = math.random(S_BORDER + 5, SCREEN_HEIGHT - S_BORDER - self.height - 5)
	self.image = imgs.crysts[math.random(1, table.getn(imgs.crysts))]
end

function Cryst:draw()
	screen:setTint((self.nuketimer <= 0) and self.color or colors.nuked)
	screen.blitRotScale(self.x, self.y, self.image, self.rot, self.scale, self.scale)
	screen:setTint()
end

function Cryst:deathflash()
	self.scale, self.x, self.y = self.scale*1.6, self.x - 0.3*self.width, self.y - 0.3*self.height
	self:draw()
	self.scale, self.x, self.y = self.scale/1.6, self.x + 0.3*self.width, self.y + 0.3*self.height
end

function Cryst:move()
	-- yay C coldet
	local rx1, ry1, rx2, ry2 = self.x, self.y, self.x+self.width, self.y+self.height
	local rect = {{rx1, ry1}, {rx2, ry2}}
	--local coldet, collided = colDetRectLineIn, false
	local coldet, collided = Coldet.rectLineIn, false
	if self.nuketimer <= 0 then
		Circle:eachLine(function(p1, p2, hor)
			--if coldet(rect, p1, p2, hor) then
			if coldet(rx1, ry1, rx2, ry2, p1[1], p1[2], p2[1], p2[2], hor) then
				collided = true
				screen:fillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT, colors.badflash)
				if hor then
					self.dir[1] = -self.dir[1] 
				else
					self.dir[1] = math.pi-self.dir[1]
				end
			end
		end)
		
		local mx, my = Vector.toCartesian(self.dir[1], self.dir[2])
		if not collided then
			self.dir[1] = self.dir[1] + self.dirchange
			if self.dir[1] > PI2 then self.dir[1] = self.dir[1] - PI2 end
			if self.dir[1] < 0 then self.dir[1] = self.dir[1] + PI2 end
			
			self.x = self.x + mx
			self.y = self.y + my
		else
			self.x = self.x + mx*1.5
			self.y = self.y + my*1.5
		end
		
		if math.random(Level.crystDirChangeProbability) == 1 then
			if self.dirchange < 0.03 then self.dirchange = self.dirchange + math.random(15)/1000 end
			if self.dirchange > -0.03 then self.dirchange = self.dirchange - math.random(15)/1000 end
		end
		
		self.rot = self.rot + self.dirchange * 80
	else
		self.nuketimer = self.nuketimer - 1
	end
	
	coldet = colDetRectLineAlt
	Fibers:eachLine(function(p1, p2, hor)
		if coldet(rect, p1, p2, hor) then
			screen:fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, colors.crystflash)
			Fibers:stop()
			sfx.breakfiber:play()
			return false
		end
	end)
end

function Cryst:testAlive()
	local rect = {{self.x, self.y}, {self.x+self.width, self.y+self.height}}
	local coldet = colDetRectRect
	local dodie = true
	Circle:eachQuad(function(r)
		if coldet(r, rect) then
			dodie = false
			return false
		end
	end) 
	if dodie then return self:die() end
	return true
end

function Cryst:die()
	if not self.boss then
		self.dead = true
		self.color = colors.deadcryst
		self.nuketimer = 0
		self:deathflash()
		Game:addScore(self.scale * self.dir[2] * 500) -- wacky formula
		Crysts:die(self)
	else
		Crysts.bosshit = true
		self.boss = false
		return true
	end
end

function Cryst:nuke()
	if not self.boss then
		self.nuketimer = Difficulty.nukeduration
	end
end


Crysts = {
	list = {},
	deadlist = {},
	bosshit = false
}

function Crysts:reset()
	self.list = {}
	self.deadlist = {}
	self.bosshit = false
end

function Crysts:die(c)
	table.remove(self.list, getIndex(self.list, c))
	table.insert(self.deadlist, c)
end

function Crysts:draw()
	for _, c in pairs(self.deadlist) do
		c:draw()
	end
	for _, c in pairs(self.list) do
		c:draw()
	end
end

function Crysts:move()
	for _, c in pairs(self.list) do
		c:move()
	end
end

function Crysts:testAlive()
	local i = 1
	self.bosshit = false
	while self.list[i] do
		if self.list[i]:testAlive() then i = i+1 end
	end
	if self.bosshit then return true end
	if table.getn(self.list) == 0 then Game:finishedLevel() end
end

function Crysts:nuke()
	for _, c in pairs(self.list) do
		c:nuke()
	end
end
