//Copyright (C) 2007 SiegeLord
//See ReadMe.txt and License.txt for copying information

#include "neonz.h"
#include "camera.h"
#include "world.h"

extern float g_fOut;

SCamera g_strCamera;

void InitCamera(float radius, float init_theta, float min_radius, float max_radius)
{
	g_strCamera.y = SCREEN_H / 2 + radius;
	g_strCamera.theta = init_theta;
	g_strCamera.x = SCREEN_W / 2;

	g_strCamera.y_max = max_radius + SCREEN_H / 2;
	g_strCamera.y_min = min_radius + SCREEN_H / 2;

	UpdateCameraPosition();
}

void UpdateCameraPosition()
{
	g_strCamera.y += g_strCamera.y_v * g_fDelta;
	g_strCamera.theta += (g_strCamera.theta_v) * g_fDelta;

	if(SnapVarTest(g_strCamera.y, g_strCamera.y_min, g_strCamera.y_max))
		g_strCamera.y_v = 0.0f;

	g_strCamera.trans.SetTranslation(g_strCamera.x, g_strCamera.y);
	g_strCamera.trans.SetRotation(g_strCamera.theta);

	//a little ugly, this makes the zoom feature zoom at the center of the screen
	transform2d trans;
	trans.SetTranslation(-SCREEN_W / 2, -SCREEN_H / 2);
	trans.TransformTransform(&g_strCamera.trans);

	trans.MakeIdentity();
	trans.SetTranslation(SCREEN_W / 2, SCREEN_H / 2);
	trans.SetScale(g_strCamera.zoom, g_strCamera.zoom);
	trans.TransformTransform(&g_strCamera.trans);
	
	g_fOut = g_strCamera.theta / AL_PI;

	SetCameraMatrix(g_strCamera.trans);
}

void HandleCamera()
{
	if(IsKeyDown(KEY_UP) || g_nMouseY < 10)
		ChangeVar(g_strCamera.y_v, g_strCamera.y_target_v / g_strCamera.zoom, g_fDelta * g_strCamera.y_a / g_strCamera.zoom);
	else if(IsKeyDown(KEY_DOWN) || g_nMouseY > SCREEN_H - 10)
		ChangeVar(g_strCamera.y_v, -g_strCamera.y_target_v / g_strCamera.zoom, g_fDelta * g_strCamera.y_a / g_strCamera.zoom);
	else
		ChangeVar(g_strCamera.y_v, 0.0f, g_fDelta * g_strCamera.y_da / g_strCamera.zoom);

	if(IsKeyDown(KEY_LEFT) || g_nMouseX < 10)
		ChangeVar(g_strCamera.theta_v, g_strCamera.theta_target_v / g_strCamera.zoom, g_fDelta * g_strCamera.theta_a / g_strCamera.zoom);
	else if(IsKeyDown(KEY_RIGHT) || g_nMouseX > SCREEN_W - 10)
		ChangeVar(g_strCamera.theta_v, -g_strCamera.theta_target_v / g_strCamera.zoom, g_fDelta * g_strCamera.theta_a / g_strCamera.zoom);
	else
		ChangeVar(g_strCamera.theta_v, 0.0f, g_fDelta * g_strCamera.theta_da / g_strCamera.zoom);

	if(IsKeyJustPressed(KEY_PGDN) || g_nMouseDZ > 0)
		g_strCamera.zoom_desired *= 2;
	else if(IsKeyJustPressed(KEY_PGUP) || g_nMouseDZ < 0)
		g_strCamera.zoom_desired /= 2;

	SnapVar(g_strCamera.zoom_desired, g_strCamera.zoom_min, g_strCamera.zoom_max);

	ChangeVar(g_strCamera.zoom, g_strCamera.zoom_desired, g_strCamera.zoom_a * (float)fabs(g_strCamera.zoom - g_strCamera.zoom_desired) * g_fDelta);

	UpdateCameraPosition();
}


vector2d GetWorldMousePos()
{
	vector2d mouse_pos(g_nMouseX, g_nMouseY);

	//here we just do a reverse transformation, see the camera function to see the forward way
	mouse_pos -= vector2d(SCREEN_W / 2, SCREEN_H / 2);
	mouse_pos /= g_strCamera.zoom;
	mouse_pos += vector2d(SCREEN_W / 2, SCREEN_H / 2);
	mouse_pos -= vector2d(g_strCamera.x, g_strCamera.y);
	mouse_pos.Rotate(-g_strCamera.theta);

	return mouse_pos;
}



void TransformWorldToView(vector2d* vec)
{
	g_strCamera.trans.TransformVector(vec);
}

void DrawCameraOrbit()
{
	DrawModeAlpha();
	float old_thick = SetLineThickness(2.0f);
	SetLineThickness(1.0f);
	DrawCircle(0, 0, g_strCamera.y - SCREEN_H / 2, -10, 0xffff4070);
	SetLineThickness(old_thick);
	DrawModeSolid();
}

void UpdateSoundParams(SSound* sound, const vector2d& position)
{
	vector2d pos = position;
	g_strCamera.trans.TransformVector(&pos);

	vector2d center_pos(SCREEN_W / 2, SCREEN_H / 2);

	pos -= center_pos;
	
	float distance = (pos.GetLength() / g_strCamera.zoom + 1000 / (g_strCamera.zoom));
	
	distance *= distance;

	float volume = (500000.0f) / (distance + 500000.0f);//hrmph... it works

	float pan = pos.x / (SCREEN_W / 2.0f);

	SetSoundVolume(sound, volume);
	SetSoundPan(sound, pan);
}
