/*
	AramakiOnline
	Copyright (C) 2008 superbacker

	This program is free software; you can redistribute it and/or modify it under the terms
	of the GNU General Public License as published by the Free Software Foundation;
	either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY
	WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
	FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this
	program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Canvas.h"
#include "World.h"
#include "MainFrame.h"

BEGIN_EVENT_TABLE(Canvas,wxGLCanvas)
	EVT_PAINT(Canvas::onPaint)
	EVT_SIZE(Canvas::onSize)
	EVT_KEY_DOWN(Canvas::onKeyDown)
	EVT_SET_FOCUS(Canvas::onSetFocus)
	EVT_KILL_FOCUS(Canvas::onKillFocus)
	EVT_IDLE(Canvas::onIdle)
END_EVENT_TABLE()

Canvas::Canvas(wxFrame *parent) : wxGLCanvas(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,0,wxGLCanvasName,0,wxNullPalette),movable(true) {
	//OpenGLを初期化
	initGL();
}

void Canvas::draw() {
	MyCharacter &myCharacter=getWorld().getMyCharacter();

	SetCurrent();

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();

	//自機に合わせて物をずらす
	glRotated(myCharacter.getDirection(),0,1,0);
	glTranslated(-myCharacter.getPosition().x,-myCharacter.getPosition().y,-myCharacter.getPosition().z);

	//描画
	getWorld().draw();

	//画面に表示
	SwapBuffers();
}

void Canvas::onPaint(wxPaintEvent &WXUNUSED(event)) {
	wxPaintDC(this);

	//ログインしていなかったら何もしない
	if (!isLoggingIn()) return;

	draw();
}

void Canvas::onSize(wxSizeEvent &event) {
	wxGLCanvas::OnSize(event);

	resetProjectionMode();

	draw();
}

void Canvas::initGL() {
	//ライト位置
	static const float lightPosition[]={0,20,19,0};
	//環境光
	static const float lightAmbient[]={0.25,0.25,0.25};

	SetCurrent();

	//デプステストを有効に
	glEnable(GL_DEPTH_TEST);

	//テクスチャのAlpha50%以上のピクセルしか表示しない
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER,0.5);

	//片面表示をオンに
	glEnable(GL_CULL_FACE);

	//ライトを設定・有効に
	glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);
	glLightfv(GL_LIGHT0,GL_AMBIENT,lightAmbient);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	//glEnable(GL_BLEND);
	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	resetProjectionMode();
}

void Canvas::checkKeyInput(int frameCount) const {
	MyCharacter &myCharacter=getWorld().getMyCharacter();

	//キー入力をチェックする
	if (wxGetKeyState(WXK_UP)) for (int i=0;i<frameCount;++i) myCharacter.goAhead();
	if (wxGetKeyState(WXK_LEFT)) for (int i=0;i<frameCount;++i) myCharacter.turnLeft();
	if (wxGetKeyState(WXK_RIGHT)) for (int i=0;i<frameCount;++i) myCharacter.turnRight();
	if (wxGetKeyState(WXK_DOWN)) for (int i=0;i<frameCount;++i) myCharacter.goBack();
}

void Canvas::resetProjectionMode() {
	int w,h;

	//クライアント領域のサイズを取得
	GetClientSize(&w,&h);

	SetCurrent();

	//行列を再設定
	glViewport(0,0,w,h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	//視点を設定
	gluPerspective(60,(double)w/h,1,80);
	gluLookAt(0,1.5,5,0,1.5,0,0,1,0);

	glMatrixMode(GL_MODELVIEW);
}

void Canvas::onSetFocus(wxFocusEvent &WXUNUSED(event)) {
	delayStopWatch.Start(0);
	movable=true;
}

void Canvas::onKillFocus(wxFocusEvent &WXUNUSED(event)) {
	movable=false;
}

void Canvas::onKeyDown(wxKeyEvent &event) {
	if (event.GetKeyCode()==WXK_TAB) {
		//発言入力欄にフォーカスをセット
		getMainFrame().setFocusToMessageText();
	}
}

void Canvas::onIdle(wxIdleEvent &event) {
	//TODO comment
	if (!isLoggingIn()) return;

	if (delayStopWatch.Time()>WAIT) {
		int frameCount=delayStopWatch.Time()/WAIT;
		delayStopWatch.Start(delayStopWatch.Time()%WAIT);
		if (movable) checkKeyInput(frameCount);
		draw();
	}

	wxMilliSleep(WAIT-delayStopWatch.Time()%WAIT);

	event.RequestMore();
}
