#include "SimpleWindow.h"
#include "SpriteModel.h"

void fkut_SimpleWindow::PushPrevStatus(void)
{
	int	i;

	for(i = 0; i < 255; i++) {
		prevKeySt[i] = drawWin->getKeyStatus((char)i, false);
	}
	for(i = 0; i < 32; i++) {
		prevSPKeySt[i] = drawWin->getSpecialKeyStatus((fk_SpecialKey)i, false);
	}
	for(i = 0; i < 3; i++) {
		prevMouseSt[i] = drawWin->getMouseStatus((fk_MouseButton)i, false);
	}

	return;
}

fkut_SimpleWindow::fkut_SimpleWindow(void)
{
	mainWin = new Fl_Window(512, 512, "FKUT Window");
	drawWin = new fk_Window(0, 0, 512, 512);

	mainWin->end();
	fk_Material::initDefault();

	light.setShape(&lightShape);
	light.setMaterial(White);
	light.getMaterial()->setAmbDiff(1.0, 1.0, 1.0);
	light.glMoveTo(0.0, 0.0, 0.0);
	light.glFocus(-1.0, -1.0, -1.0);

	scene.setBlendStatus(true);
	scene.entryCamera(&camera);
	scene.entryModel(&light);

	drawWin->setScene(&scene);

	setFPS(60);

	camera.glMoveTo(0.0, 0.0, 100.0);
	camera.glFocus(0.0, 0.0, 0.0);
	camera.glUpvec(0.0, 1.0, 0.0);

	tb = new fk_TrackBall(drawWin, &camera);
	tbFlag = false;

	ref_camera = &camera;

	PushPrevStatus();

	return;
}

fkut_SimpleWindow::~fkut_SimpleWindow(void)
{
	drawWin->hide();
	mainWin->hide();

	delete drawWin;
	delete mainWin;
}

void fkut_SimpleWindow::setSize(int argW, int argH)
{
	mainWin->resize(mainWin->x(), mainWin->y(), argW, argH);
	drawWin->resizeWindow(0, 0, argW, argH);

	return;
}

void fkut_SimpleWindow::setBGColor(double r, double g, double b)
{
	scene.setBGColor((float)r, (float)g, (float)b);

	return;
}

void fkut_SimpleWindow::setFPS(int argFPS)
{
	if(argFPS == 0) {
		fps = 0;
		fps_admin.OnFrameSkip(false);
	} else {
		fps = argFPS;
		fps_admin.OnFrameSkip(true);
		fps_admin.SetFPS(argFPS);
	}

	return;
}

void fkut_SimpleWindow::setTrackBallMode(bool mode)
{
	tbFlag = mode;

	return;
}

void fkut_SimpleWindow::showGuide(fkut_GuideMode mode)
{
	guide.entryScene(&scene, mode);
}

void fkut_SimpleWindow::hideGuide(void)
{
	guide.removeScene(&scene);
}

void fkut_SimpleWindow::setCameraPos(double x, double y, double z)
{
	ref_camera->glMoveTo(x, y, z);
}

void fkut_SimpleWindow::setCameraFocus(double x, double y, double z)
{
	ref_camera->glFocus(x, y, z);
	tb->setLookTo(fk_Vector(x, y, z));

	return;
}

void fkut_SimpleWindow::setCameraModel(fk_Model &model)
{
	ref_camera = &model;
	scene.entryCamera(ref_camera);

	return;
}

void fkut_SimpleWindow::setCameraDefault(void)
{
	ref_camera = &camera;
	scene.entryCamera(ref_camera);

	return;
}

void fkut_SimpleWindow::entry(fk_Model &model)
{
	scene.entryModel(&model);
}

void fkut_SimpleWindow::remove(fk_Model &model)
{
	scene.removeModel(&model);
}

void fkut_SimpleWindow::entry(fk_Model &model, fkut_GuideObject &argGuide)
{
	argGuide.setParent(&model);
	argGuide.entryScene(&scene);
	scene.entryModel(&model);
}

void fkut_SimpleWindow::remove(fk_Model &model, fkut_GuideObject &argGuide)
{
	argGuide.setParent(NULL);
	argGuide.removeScene(&scene);
	scene.removeModel(&model);
}

void fkut_SimpleWindow::entry(fkut_SpriteModel &model)
{
	model.MakePixelBase(drawWin, &scene);
	scene.entryOverlayModel(&model);
}

void fkut_SimpleWindow::remove(fkut_SpriteModel &model)
{
	scene.removeOverlayModel(&model);
}

void fkut_SimpleWindow::open(void)
{
	mainWin->show();
	drawWin->show();

	return;
}

bool fkut_SimpleWindow::update(void)
{
	PushPrevStatus();
	if(fps != 0) fps_admin.TimeRegular();

	if(mainWin->visible() == 0) {
		if(Fl::wait() == 0) {
			return false;
		} else {
			return true;
		}
	}

	if(fps_admin.GetDrawFlag() || fps == 0) drawWin->drawWindow();
	if(Fl::check() == 0) return false;

	if(tbFlag) tb->update();

	return true;
}

fkut_SwitchStatus GetSwitchStatus(bool now, bool pre)
{
	switch((int)now*2 + (int)pre) {
	case 0:
		return FKUT_SW_RELEASE;
	case 1:
		return FKUT_SW_UP;
	case 2:
		return FKUT_SW_DOWN;
	case 3:
		return FKUT_SW_PRESS;
	default:
		return FKUT_SW_RELEASE;
	}
}

fkut_SwitchStatus fkut_SimpleWindow::getKeyStatus(char argKey)
{
	return GetSwitchStatus(drawWin->getKeyStatus(argKey, false), prevKeySt[(int)argKey]);
}

fkut_SwitchStatus fkut_SimpleWindow::getSpecialKeyStatus(fk_SpecialKey argKey)
{
	return GetSwitchStatus(drawWin->getSpecialKeyStatus(argKey, false), prevSPKeySt[(int)argKey]);
}

fkut_SwitchStatus fkut_SimpleWindow::getMouseStatus(fk_MouseButton argButton)
{
	return GetSwitchStatus(drawWin->getMouseStatus(argButton, false), prevMouseSt[(int)argButton]);
}

fk_Vector fkut_SimpleWindow::getMousePosition(void)
{
	int			x, y;
	fk_Vector	retPos;

	drawWin->getMousePosition(&x, &y, false);

	retPos.x = (double)x;
	retPos.y = (double)y;
	retPos.z = 0.0;

	return retPos;
}

bool fkut_SimpleWindow::isModelPicked(fk_Model &model, int pixel, int mouseX, int mouseY)
{
	static fk_PickData	pick;
	const bool orgMode = model.getPickMode();

	if(mouseX == -1 || mouseY == -1) {
		drawWin->getMousePosition(&mouseX, &mouseY);
	}
	if(mouseX == -1 || mouseY == -1) return false;

	model.setPickMode(true);
	drawWin->getPickModel(&pick, pixel, mouseX, mouseY);
	model.setPickMode(orgMode);

	for(int i = 0; i < pick.getSize(); i++) {
		if(pick.getModel(i) == &model) return true;
	}

	return false;
}

void fkut_SimpleWindow::setGuideAxisWidth(double width)
{
	guide.setAxisWidth(width);
}

void fkut_SimpleWindow::setGuideGridWidth(double width)
{
	guide.setGridWidth(width);
}

void fkut_SimpleWindow::setGuideScale(double scale)
{
	guide.setScale(scale);
}

void fkut_SimpleWindow::setGuideNum(int num)
{
	guide.setNum(num);
}
