-- TODO: This is one of the least organized Lua files in the project.
--   Needs some sanity.

writeConsole("Player init...\n");


------------------------------------------------------------------------
-- Bullets class (and demonstration of subclassing stupidity)p
------------------------------------------------------------------------

-- An example of subclassing off the main Entity class. Entity is constructed
-- in the C++ code and mostly consists of C++ function bindings so we can
-- fiddle around with the entities.
AClass = Entity:createSubClass();

------------------------------------------------------------------------------
-- An example of a child class of something else.

-- We don't need to reimplement createSubClass(). This will create a game
-- object WITHOUT actually instantiating it in the engine. Basically just sets
-- up metatables and all that good stuff.
BClass = AClass:createSubClass();

function BClass:setFrame()
	local vx, vy = self:getVel();
	local threshold = 6;
	
	if vx > threshold then
		-- Right
		self:setSpriteFrame(0, 0, 32, 16);
		
		if vy > threshold then
			-- Up-right
			self:setSpriteFrame(64, 0, 96, 32);
		elseif vy < threshold * -1 then
			-- Down-right
			self:setSpriteFrame(96, 0, 128, 32);
		end
		
	elseif vx < threshold * -1 then
		-- Left
		self:setSpriteFrame(0, 16, 32, 32);
		
		if vy > threshold then
			-- Up-left
			self:setSpriteFrame(128, 0, 160, 32);
		elseif vy < threshold * -1 then
			-- Down-left
			self:setSpriteFrame(160, 0, 192, 32);
		end
	else
		if vy > threshold then
			-- Up
			self:setSpriteFrame(32, 0, 48, 32);
		elseif vy < threshold * -1 then
			-- Down
			self:setSpriteFrame(48, 0, 64, 32);
		end
	end
end

-- All objects should have an update() function.
-- This is called every frame.
-- It is NOT called when the object is very far away (one or more
-- entire screens away). This non-calling functionality has yet to be
-- implemented, however. Use timer hooks for things that have to act
-- when not nearby (not implemented yet).
function BClass:update()
	--io.write("BClass ("..self:getName()..") update\n");

	self:setFrame();
	
	local age = self:getAge();
	--if age > 90 then
	if not self:getOnScreen() then
		self:die();
	end
	
	x, y = self:getPos();
	
	--if y < -256 then
	--	self:die()
	--end
end

-- init() is called when an object is created.
function BClass:init()
	-- Be sure to call init() in the parent class! I know the syntax is a
	-- little weird, but whatever. Be sure to pass self as a parameter and
	-- use the '.' instead of ':', or it'll have the un-instantiated AClass as
	-- its self variable.
	AClass.init(self);
	
	--io.write("BClass ("..self:getName()..") init\n");
	
	self:setTexture("lilyshots.tga");
	
	self:setSize(16, 16);
	self:setSpriteFrame(0, 0, 0, 0);
	
	self:setBlockable(true);
	--self:setBlocker(true);
	self:setBlocker(false);
	
	--self:setForceUpdate(true);
	
	self.isPlayerBullet = false;
    self:setFullbright(true);
end

function BClass:initFromSave(saveData)
	self.isPlayerBullet = saveData.isPlayerBullet;
end

function BClass:save()
	return {
		isPlayerBullet = self.isPlayerBullet
	};
end

------------------------------------------------------------------------

CClass = BClass:createSubClass();





------------------------------------------------------------------------
-- Shell casings class.
------------------------------------------------------------------------

EjectedShell = Entity:createSubClass();
function EjectedShell:init()
	Entity.init(self);
	self:setBlockable(true);
	self:setBlocker(false);
	self:setTexture("lilyshots.tga");
	self:setSpriteFrame(0, 40, 8, 48);
	self:setBounciness(0.8);
	self:setSize(4, 4);
	self.animFrame = 0;
	--self:setLabelFont("data/font1.png");
	self:setGravityInfluence(1);
end

function EjectedShell:update()
	local dx, dy = self:getVel();
	self.animFrame = self.animFrame + (math.abs(dx) + math.abs(dy)) / 16;
	local spritex = math.fmod(math.floor(self.animFrame), 8) * 8;
	self:setSpriteFrame(spritex, 40, spritex + 8, 48);
	
	local age = self:getAge();
	if age > 60 then
		local left = 1 - ((age - 60) / 30);
		self:setAlpha(left);
	end
	
	if age > 90 then
		self:die();
	end
	
	dx = dx * 0.9;
	dy = dy * 0.9;
	self:setVel(dx, dy);
	
	--self:setLabel(self:getAge());
end






------------------------------------------------------------------------
-- Target cursor for thrown objects.
------------------------------------------------------------------------

Target = Entity:createSubClass();
function Target:init()
	Entity.init(self);
	self:setBlockable(false);
	self:setBlocker(false);
	self:setSize(16, 16);
	self:setTexture("sampleSprites.tga");
	self:setSpriteFrame(0, 0, 16, 16);
	
	self.rangeFromShooter = 100;
	self.myShooter = nil;
    self:setLayer(4);
end

function Target:setMyShooter(shooter)
	self.myShooter = shooter;
end

function Target:update()

	self:setVel(0, 0);
	
	local age = self:getAge() / 10.0;
	local x = math.cos(age) * self.rangeFromShooter;
	local y = math.sin(age) * self.rangeFromShooter;
	
	local sx;
	local sy;
	
	--sx, sy = self.myShooter:getPos();
	
	--self:setPos(sx + x, sy + y);
end


------------------------------------------------------------------------
-- Player class.
------------------------------------------------------------------------

Shooter = Entity:createSubClass();
function Shooter:init()
	Entity.init(self);
	self:setBlockable(true);
	self:setBlocker(false);
	self:setSize(48, 100);
	self:setTexture("data/lily6.tga");
	self:setSpriteFrame(0, 0, 288, 144);
	self:setBounciness(0);
	self:setGravityInfluence(1);

	-- This isn't recommended, but whatever.
	self:setName("player");

	self.jumpInitiated = false;
	self.droppingDown = 0;
	self.turnAnimFrame = 0;
	
	-- 0 = left, 1 = right
	self.moveDir = 0;
	self.animFrame = 0;
	
	self.shotAnimFrame = 0;
	self.moveAnimFrame = 0;
	self.fallAnimFrame = 0;
	self.landAnimFrame = 0;
	self.jumpAnimFrame = 0;
	self.idleAnimFrame = 0;
	self.shotCoolDown = 0;
	self.throwAnimFrame = 0;
	self.throwAngle = 0;
	self.throwTarget = nil;
	self.timeSinceLastShot = 0;
	
end

function Shooter:initFromSave(saveData)
	self.jumpInitiated = saveData.jumpInitiated;
	self.droppingDown  = saveData.droppingDown;
	self.turnAnimFrame = saveData.turnAnimFrame;
	self.moveDir       = saveData.moveDir;
	self.animFrame     = saveData.animFrame;
	self.shotAnimFrame = saveData.shotAnimFrame;
	self.moveAnimFrame = saveData.moveAnimFrame;
	self.fallAnimFrame = saveData.fallAnimFrame;
	self.landAnimFrame = saveData.landAnimFrame;
	self.jumpAnimFrame = saveData.jumpAnimFrame;
	self.idleAnimFrame = saveData.idleAnimFrame;
	self.shotCoolDown  = saveData.shotCoolDown;
	self.throwAnimFrame = saveData.throwAnimFrame;
	self.throwAngle = saveData.throwAngle;
	self.throwTarget = nil;
	self.timeSinceLastShot = saveData.timeSinceLastShot;
end

function Shooter:save()
	return {
		jumpInitiated = self.jumpInitiated,
		droppingDown  = self.droppingDown,
		turnAnimFrame = self.turnAnimFrame,
		moveDir       = self.moveDir,
		animFrame     = self.animFrame,
		shotAnimFrame = self.shotAnimFrame,
		moveAnimFrame = self.moveAnimFrame,
		fallAnimFrame = self.fallAnimFrame,
		landAnimFrame = self.landAnimFrame,
		jumpAnimFrame = self.jumpAnimFrame,
		idleAnimFrame = self.idleAnimFrame,
		shotCoolDown  = self.shotCoolDown,
		throwAnimFrame = self.throwAnimFrame,
		throwAngle = self.throwAngle,
		timeSinceLastShot = self.timeSinceLastShot,
	};
end

function Shooter:update()

   local mx, my = self:getPos();

   local joyAxis1 = getControlValue(1) - getControlValue(0);
   local joyAxis0 = getControlValue(3) - getControlValue(2);

   local shootButton   = getControlBoolValue(4);
   local jumpButton    = getControlBoolValue(5);
   local grenadeButton = getControlBoolValue(6);

   -- Axis movement.
   local speed = 12;
   local vx, vy = self:getVel();
   local oldvy = vy;
   local animSpeed = 0.5;
   local movedThisFrame = false;

   if self.throwAnimFrame <= 0 and not self.wasHoldingButton2 then
      if joyAxis0 < -32 then
         if not shootButton or not self:getOnGround() then
            vx = vx - speed;
         end
         if self.moveDir == 1 and math.abs(joyAxis1) < 32 then
            self.turnAnimFrame = 4.99;
         end
         self.moveDir = 0;
         movedThisFrame = true;
      end
      if joyAxis0 > 32 then
         if not shootButton or not self:getOnGround() then
            vx = vx + speed;
         end
         if self.moveDir == 0 and math.abs(joyAxis1) < 32 then
            self.turnAnimFrame = 4.99;
         end
         self.moveDir = 1;
         movedThisFrame = true;
      end
   end
	
	-- Grenade aiming.
	if self.wasHoldingButton2 then
		local angleSpeed = 0.1;
		if joyAxis0 < -32 then
			self.throwAngle = self.throwAngle + angleSpeed;
		end
		if joyAxis0 > 32 then
			self.throwAngle = self.throwAngle - angleSpeed;
		end

		local throwCos = math.cos(self.throwAngle);
		if throwCos < 0 then
			self.moveDir = 0;
		end
		if throwCos > 0 then
			self.moveDir = 1;
		end
		
		if not self.throwTarget then
			self.throwTarget = Target:create();
		end
		
		local x, y = self:getPos();
		local range = 128;
		self.throwTarget:setPos(x + math.cos(self.throwAngle) * range, y + math.sin(self.throwAngle) * range);
	else
		if self.throwTarget then
			self.throwTarget:die();
			self.throwTarget = nil;
		end
	end
	
	-- Grenade throwing.
	self.throwAnimFrame = self.throwAnimFrame - 1;
	if self.throwAnimFrame < 0 then 
		self.throwAnimFrame = 0;
	end
	if grenadeButton and not self.wasHoldingButton2 and self.throwAnimFrame <= 0 then
		self.wasHoldingButton2 = true;
		self.throwAngle = 3.14159 / 4;
		if self.moveDir == 0 then
			self.throwAngle = 3.14159 * (3/4);
		end
	end
	
	if not grenadeButton and self.wasHoldingButton2 == true then
		if not shootButton then -- Cancel throw with shoot
			self.throwAnimFrame = 10;
			local molotov = Molotov:create();
			--local molotov = Grenade:create();
			
			local throwSpeed = 32;
			local dx = math.cos(self.throwAngle) * throwSpeed;
			local dy = math.sin(self.throwAngle) * throwSpeed;
			local x, y = self:getPos();
			molotov:setPos(x + dx, y + dy);
			molotov:setVel(dx, dy);
		end		
		self.wasHoldingButton2 = false;
	end

	-- Shooting.
	self.shotCoolDown = 0;
	self.timeSinceLastShot = self.timeSinceLastShot + 1;
	local shotThisFrame = false;
	if shootButton and self.shotCoolDown <= 0 then
		local nx, ny = self:getPos();
		local reallyShootThisFrame = false;
		
		--math.fmod(self:getAge(), 4) == 0 
		if self.timeSinceLastShot > 3 then
			local newShell = EjectedShell:create();
			newShell:setPos(nx, ny + 32);
            newShell:setLayer(self:getLayer());
			local shelldx = math.random(8) - 4;
			local shelldy = math.random(4) + 12;
			if self.moveDir == 1 then
				shelldx = shelldx - 8;
			else
				shelldx = shelldx + 8;
			end
			newShell:setVel(shelldx, shelldy);
			
			playSound("data/gun1.ogg");
			reallyShootThisFrame = true;
		end
		
		if reallyShootThisFrame then
			self.timeSinceLastShot = 0;
			
			self.shotCoolDown = 2;
			local newOb = CClass:create();
            newOb:setLayer(self:getLayer());
			local shotSpeed = 32;
			local shotVariance = math.random(5) - 2.5;
			ny = ny + 16;
			
			if self.moveDir == 1 then
				-- Right
				newOb:setVel(shotSpeed, shotVariance);
				nx = nx + 80;
			else
				-- Left
				newOb:setVel(shotSpeed * -1, shotVariance);
				nx = nx - 80;
			end
			
			if joyAxis1 < -32 and joyAxis0 < -32 then
				-- Up left
				newOb:setVel(-0.707106781 * shotSpeed + shotVariance / 2, 0.707106781 * shotSpeed + shotVariance / 2);
				ny = ny + 64;
				nx = nx + 16;
			elseif joyAxis1 < -32 and joyAxis0 > 32 then
				-- Up right
				newOb:setVel(0.707106781 * shotSpeed + shotVariance / 2, 0.707106781 * shotSpeed - shotVariance / 2);
				ny = ny + 64;
				nx = nx - 16;
			elseif joyAxis1 > 32 and joyAxis0 < -32 then
				-- Down left
				newOb:setVel(-0.707106781 * shotSpeed - shotVariance / 2, -0.707106781 * shotSpeed + shotVariance / 2);
				ny = ny - 48;
				nx = nx + 16;
			elseif joyAxis1 > 32 and joyAxis0 > 32 then
				-- Down right
				newOb:setVel(0.707106781 * shotSpeed - shotVariance / 2, -0.707106781 * shotSpeed - shotVariance / 2);
				ny = ny - 48;
				nx = nx - 16;
			elseif joyAxis1 > 32 then
				-- Down
				newOb:setVel(shotVariance, -shotSpeed);
				nx, ny = self:getPos();
				ny = ny - 64;
			elseif joyAxis1 < -32 then
				-- Up
				newOb:setVel(shotVariance, shotSpeed);
				nx, ny = self:getPos();
				ny = ny + 96;
			else
			end
			
			newOb:setPos(nx, ny);
			
			newOb:setSize(16, 16);
			newOb:setBlocker(false);
			newOb:setBlockable(false);
			newOb:setGravityInfluence(0);
			newOb.isPlayerBullet = true;
			
			newOb:setFrame();
			
		end
		
		shotThisFrame = true;
	end
	

	-- Turning animation
	self.turnAnimFrame = self.turnAnimFrame - animSpeed;
	if self.turnAnimFrame < 0 then
		self.turnAnimFrame = 0;
	end

	-- Falling through the floor.	
	self:setIgnoreBlockDown(false);
	if joyAxis1 > 8192 and jumpButton and self.droppingDown < 10 then
		self:setIgnoreBlockDown(true);
		self.droppingDown = self.droppingDown + 1;
		self.jumpInitiated = true;
	end
	if not jumpButton then
		self.droppingDown = 0;
	end
	
	-- Jumping.
	if self:getOnGround() then
		if not jumpButton then
			self.jumpInitiated = false;
		end
		if jumpButton and self.jumpInitiated == false and not self:getIgnoreBlockDown() then
			--vy = 30;
			vy = 48;
			self.jumpInitiated = true;
		end
	end

	if self.jumpInitiated and vy > 0 and not jumpButton then
	   -- We're in a jump, but the player has released the jump button
	   -- early. Cancel the jump.
	   vy = 0;
	end
	
	self:setVel(vx * 0.5, vy * 0.95);
	
	
	
	--if self.moveDir == 0 then
		--spritey = spritey + 144;
	   --setFlipHorizontal(true)
	--end

	self:setFlipHorizontal(self.moveDir == 0);
	
	--if self.turnAnimFrame > 0 then
	--	if self.moveDir == 0 then
	--		spritey = 144;
	--	else
	--		spritey = 0;
	--	end
	--end
	
	if self.landAnimFrame > 0 then
		self.landAnimFrame = self.landAnimFrame - animSpeed;
	else
		self.landAnimFrame = 0;
	end
	
	--if oldvy < -8 then
	if not self:getOnGround() then
		self.fallAnimFrame = self.fallAnimFrame + animSpeed;
	else
		if self.fallAnimFrame > 0 then
			self.landAnimFrame = 2.99;
		end
	
		self.fallAnimFrame = 0;
	end
	
	if oldvy > 0 then
		self.jumpAnimFrame = self.jumpAnimFrame + (animSpeed / 2);
	else
		if self.jumpAnimFrame > 0 then
			self.fallAnimFrame = 1;
		end
		self.jumpAnimFrame = 0;
	end
	
	self.idleAnimFrame = self.idleAnimFrame + (animSpeed / 4);
	if math.floor(self.idleAnimFrame) > 2 then
		self.idleAnimFrame = 0;
	end
	
	-- TODO: Remove this.
	local spriteh = 144;
	local spritew = 288;
	local spritex = 0;
	local spritey = 0;
	
	local spriteRow = -1;
	local spriteCol = -1;
	
	-- Begin godawful, ugly block of crap to determine which sprite to
	-- draw.

	if self.jumpAnimFrame > 0 then
	   
	   -- In the jumping animation.

	   spriteRow = 8;
	   spriteCol = 1;

	   --spritey = 2448;
	   --spriteh = 288;
	   --self:setSpriteOffset(0, 48);
	   
	   local intFrame = (math.floor(self.jumpAnimFrame) - 1);
	   if math.fmod(intFrame, 2) == 0 then
		  --spritex = 1 * spritew;
		  spriteCol = 2;
	   elseif math.fmod(intFrame + 1, 4) == 0 then
		  --spritex = 2 * spritew;
		  spriteCol = 3;
	   else
		  spriteCol = 1;
		  --spritex = 0;
	   end
	   
	elseif self.landAnimFrame > 0 then
	   --spritex = (2 - math.floor(self.landAnimFrame)) * 288;
	   --spritey = 1584 + 384;

	   spriteCol = math.floor(2 - math.floor(self.landAnimFrame)) + 1;
	   spriteRow = 7;

	   --self:setSpriteOffset(8, -16);
	   --if self.moveDir == 1 then
	   --	spritey = spritey + 384;
	   --	self:setSpriteOffset(-8, -16);
	   --end
	elseif math.floor(self.fallAnimFrame) > 0 then
		local intFrame = (math.floor(self.fallAnimFrame) - 1);
	
		if intFrame > 5 then
			-- In the looping portion.
			local actualFrame = intFrame - 5;
			if math.fmod(actualFrame - 1, 2) == 0 then
				intFrame = 4;
			elseif math.fmod(actualFrame - 2, 4) == 0 then
				intFrame = 5;
			elseif math.fmod(actualFrame, 4) == 0 then
				intFrame = 3;
			else
				writeConsole("Your math sucks.\n");
			end
		end
		
		--spritex = intFrame * 288;
		--spritey = 1392 + 384;
		--self:setSpriteOffset(8, -16);

		spriteCol = intFrame + 1;
		spriteRow = 6;

		--if self.moveDir == 1 then
		--	spritey = spritey + 384;
		--	self:setSpriteOffset(-8, -16);
		--end
				
	elseif self.wasHoldingButton2 then
	
	   -- Grenade held frame

	   --spritex = 0;
	   --spritey = 3312;
		
	   spriteRow = 10;
	   spriteCol = 1;

		--if self.moveDir == 0 then
		--	spritey = spritey + 144;
		--end

		--self:setSpriteOffset(0, 0);
		
	elseif self.throwAnimFrame > 0 then
	
	   -- Throwing animation

	   --spritex = 288;
	   --spritey = 3312;

	   spriteRow = 10;
	   spriteCol = 2;
	   
	   --if self.moveDir == 0 then
	   --	spritey = spritey + 144;
	   --end

	   --self:setSpriteOffset(0, 0);
	
	elseif movedThisFrame and self.turnAnimFrame <= 0 and not shotThisFrame then

		--spritex = math.floor(self.moveAnimFrame) * 288;
		--spritey = 1056 + 144;
		
		spriteCol = math.floor(self.moveAnimFrame) + 1;
		spriteRow = 5;

		--if self.moveDir == 1 then
		--	spritey = spritey + 144;
		--end
		self.moveAnimFrame = self.moveAnimFrame + animSpeed;
		if self.moveAnimFrame >= 5 then
			self.moveAnimFrame = 0;
		end
		--self:setSpriteOffset(0, 0);
	
	 else

		self.moveAnimFrame = 0;

		if self.turnAnimFrame > 0 then
			--spritex = math.floor(self.turnAnimFrame) * 288;
		   spriteCol = math.floor(self.turnAnimFrame) + 1;
		   spriteRow = 1;
		else
		   spriteCol = math.floor(self.idleAnimFrame) + 1;
		   spriteRow = 9;
		   --spritex = math.floor(self.idleAnimFrame) * 288;
		   --spritey = 2880 + 144;

		   --if self.moveDir == 1 then
		   --	spritey = spritey + 144;
		   --end
		end
		
		
		self:setSpriteOffset(0, 0);
		if shotThisFrame and self.turnAnimFrame <= 0 then
		   --spritex = 0;
		   --spritey = 144;

		   spriteCol = 1;
		   spriteRow = 2;

		   if self.shotAnimFrame > 0 then
			  --spritex = 288;

			  spriteCol = 2;

			  self.shotAnimFrame = 0;
		   else
			  self.shotAnimFrame = self.shotAnimFrame + 1;
		   end
		   
		   --if self.moveDir == 1 then
		   
		   --spritex = spritex + (288 * 2);
		   spriteCol = spriteCol + 2;
		   
		   --end
		   
		   if joyAxis1 < -32 then
			  if joyAxis0 < -32 or joyAxis0 > 32 then
				 -- Up-angle
				 --spritey = spritey + 144;
				 spriteRow = spriteRow + 1;
			  else
				 -- Just up
				 --spritex = spritex - (288 * 2);
				 spriteCol = spriteCol - 2;

				 --spritey = spritey + (144 * 4);

				 --spritey = spritey + 144;
				 spriteRow = spriteRow + 1;

				 --self:setSpriteOffset(0, -20);
			  end
		   end
		   if joyAxis1 > 32 then
			  if joyAxis0 < -32 or joyAxis0 > 32 then
				 -- Down-angle
				 --spritey = spritey + (144 * 2);

				 spriteRow = spriteRow + 2;
				 spriteCol = spriteCol - 2;
				 
			  else
				 -- Just down
				 --spritex = spritex - (288 * 2);
				 --spriteRow = spriteRow 1 2;
				 --spriteCol = spriteCol - 2;

				 spriteRow = 2;
				 spriteCol = spriteCol - 2;

				 --spritey = spritey + (144 * 3);
			  end
		   end
		else
			self.shotAnimFrame = 0;
		end
	end

	if spriteRow > -1 and spriteCol > -1 then
	   
	   local rs = spriteDefs[self:getTexture()][spriteRow][spriteCol];

	   self:setSpriteFrame(rs[1], rs[2], rs[3], rs[4]);
	   self:setSpriteBottomCenter(rs[5], rs[6]);

	   --writeConsole("Alternate used: "
		--			..rs[1].." "
		--			..rs[2].." "
		--			..rs[3].." "
		--			..rs[4].." "
		--			..rs[5].." "
		--			..rs[6].."\n");

	else

	   --self:setSpriteFrame(spritex, spritey, spritex + spritew, spritey + spriteh);

	end

	--self:setFlipHorizontal(self.moveDir == 1);

end


ShooterSpawn = createSpawnType("ShooterSpawn", Shooter, "sampleSprites.tga", {x1=16, y1=0, x2=32, y2=16});
ShooterSpawn.customName = "player"; -- This will pop up if there is no name already assigned for it.


