#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TinyLibrary.hpp"
#include "Player.hpp"
#include "BgMap.hpp"
#include "Global.hpp"
#include "Resource.hpp"

void MainLoop_Setup(void)
{
	Global::Initialize();
	Screen::Initialize(8);
	Controller::Initialize();
	SoundPlayer::Initialize(11025);
	Global& global = Global::GetInstance();
	global.phase = Global::PHASE_LOGO;
	global.back_color = 0;
	// ゲームデータ読み込み
	TinyFile file;
	if(file.Open("SuperOteme/SuperOteme.sav", TinyFile::READ) == true)
	{
		memset(&global.gamedata, 0, sizeof(global.gamedata));
		size_t size = file.GetSize();
		file.Read(&global.gamedata, size);
		file.Close();
		if(size == (sizeof(int) * 2))
		{
			global.gamedata.volume = 10;
		}
	}
	SoundPlayer& sound_player = SoundPlayer::GetInstance();
	SoundData* sound_data = GetSoundData(SOUND_BGM);
	global.bgm_handle = sound_player.Append(0, "SuperOteme/bgm.adp", true, SoundPlayer::ADP);
	if(global.bgm_handle == -1)
	{
		global.bgm_handle = sound_player.Append(0, "SuperOteme/bgm.raw", true, SoundPlayer::RAW);
		if(global.bgm_handle == -1)
		{
			global.bgm_handle = sound_player.Append(0, sound_data->buffer, sound_data->size, true, SoundPlayer::RAW);
		}
	}
	sound_data = GetSoundData(SOUND_PIYO);
	global.piyo_handle = sound_player.Append(1, sound_data->buffer, sound_data->size, false, SoundPlayer::RAW);
	sound_data = GetSoundData(SOUND_JUMP);
	global.jump_handle = sound_player.Append(2, sound_data->buffer, sound_data->size, false, SoundPlayer::RAW);
	sound_data = GetSoundData(SOUND_KNOCKDOWN);
	global.knockdown_handle = sound_player.Append(1, sound_data->buffer, sound_data->size, false, SoundPlayer::RAW);
	SoundStream& sound_stream = SoundStream::GetInstance();
	sound_stream.SetVolume(global.gamedata.volume);
}

void MainLoop_Finalize(void)
{
	SoundPlayer::Finalize();
	Controller::Finalize();
	Screen::Finalize();
	Global::Finalize();
}

void MainLoop_Loop(void)
{
	ImageData* image_data;
	Global& global = Global::GetInstance();
	Screen& screen = Screen::GetInstance();
	Controller& controller = Controller::GetInstance();
	controller.Update();
	screen.Clear(global.back_color);
	screen.DrawBegin();
	unsigned int button = controller.GetButton();
	bool status;
	int draw_x;
	int draw_y;
	switch(global.phase)
	{
	case Global::PHASE_LOGO:
		image_data = GetImageData(LOGO);
		draw_x = (Screen::WIDTH - image_data->width) / 2;
		draw_y = (Screen::HEIGHT - image_data->height) / 2;
		screen.DrawSprite(image_data->buffer, draw_x, draw_y, image_data->width, image_data->height, 0);
		screen.DrawNumberFont(Screen::CENTER, 25, "super-meteor.com");
		global.back_color = 0;
		if((global.button_before == 0) && (button & (Controller::BUTTON_1 | Controller::BUTTON_2)))
		{
			global.phase = Global::PHASE_TITLE;
		}
		++ global.count;
		if(global.count > 30 * 5)
		{
			global.phase = Global::PHASE_TITLE;
			global.count = 0;
		}
		break;
	case Global::PHASE_TITLE:
		image_data = GetImageData(TITLE);
		draw_x = (Screen::WIDTH - image_data->width) / 2;
		draw_y = (Screen::HEIGHT - image_data->height) / 2;
		screen.DrawSprite(image_data->buffer, draw_x, draw_y, image_data->width, image_data->height, 0);
		global.back_color = 0;
		if((global.button_before == 0) && (button & (Controller::BUTTON_1 | Controller::BUTTON_2)))
		{
			global.phase = Global::PHASE_TITLE2;
		}
		++ global.count;
		if(global.count > 30 * 5)
		{
			global.phase = Global::PHASE_TITLE2;
			global.count = 0;
		}
		break;
	case Global::PHASE_TITLE2:
		image_data = GetImageData(TITLE2);
		draw_x = (Screen::WIDTH - image_data->width) / 2;
		draw_y = (Screen::HEIGHT - image_data->height) / 2;
		screen.DrawSprite(image_data->buffer, draw_x, draw_y, image_data->width, image_data->height, 0);
		screen.DrawNumberFont(Screen::LEFT, 0, "%8d", global.gamedata.score);
		screen.DrawNumberFont(Screen::RIGHT, 0, "%8d", global.gamedata.highscore);
		screen.DrawNumberFont(Screen::LEFT, Screen::HEIGHT - 30, "Press button");
		screen.DrawNumberFont(Screen::RIGHT, Screen::HEIGHT - 24, "to game start!");
		global.back_color = 0;
		if((global.button_before == 0) && (button & (Controller::BUTTON_1 | Controller::BUTTON_2)))
		{
			global.phase = Global::PHASE_INITIALIZE_GAME;
			// ゲームデータ書き込み
			TinyFile file;
			if(file.Open("SuperOteme/SuperOteme.sav", TinyFile::WRITE) == true)
			{
				file.Write(&global.gamedata, sizeof(global.gamedata));
				file.Close();
			}
		}
		++ global.count;
		if(global.count > 30 * 10)
		{
			global.phase = Global::PHASE_LOGO;
			global.count = 0;
		}
		if((global.count % 16) < 8)
		{
			image_data = GetImageData(METEOR_1);
			screen.DrawSprite(image_data->buffer, 32, 44, image_data->width, image_data->height, 0);
		}
		else
		{
			image_data = GetImageData(METEOR_2);
			screen.DrawSprite(image_data->buffer, 32, 44, image_data->width, image_data->height, 0);
		}
		{
			SoundPlayer& sound_player = SoundPlayer::GetInstance();
			SoundStream& sound_stream = SoundStream::GetInstance();
			int volume = global.gamedata.volume;
			if(!(global.button_before & Controller::BUTTON_UP) && (button & Controller::BUTTON_UP))
			{
				++ volume;
				if(volume > 10)
				{
					volume = 10;
				}
				sound_player.Play(global.piyo_handle);
				global.count = 0;
			}
			else if(!(global.button_before & Controller::BUTTON_DOWN) && (button & Controller::BUTTON_DOWN))
			{
				-- volume;
				if(volume < 0)
				{
					volume = 0;
				}
				sound_player.Play(global.piyo_handle);
				global.count = 0;
			}
			sound_stream.SetVolume(volume);
			global.gamedata.volume = volume;
		}
		break;
	case Global::PHASE_INITIALIZE_GAME:
		global.back_color = 0;
		global.game.Initialize(1);
		global.phase = Global::PHASE_GAME;
		break;
	case Global::PHASE_GAME:
		status = global.game.Update();
		global.game.Draw();
		global.back_color = global.game.GetBackColor();
		if(status == true)
		{
			global.game.Finalize();
			global.phase = Global::PHASE_LOGO;
			global.count = 0;
			// ゲームデータ書き込み
			TinyFile file;
			if(file.Open("SuperOteme/SuperOteme.sav", TinyFile::WRITE) == true)
			{
				file.Write(&global.gamedata, sizeof(global.gamedata));
				file.Close();
			}
		}
		break;
	}
	screen.DrawEnd();
	global.button_before = button;
}

void MainLoop_NoWaitLoop(void)
{
	SoundPlayer& sound_player = SoundPlayer::GetInstance();
	sound_player.Update();
}
