
/*
 * The MIT License
 *
 * Copyright 2013 Dra0211.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package kinugasa.game;

import java.awt.Graphics2D;
import kinugasa.contents.resource.Nameable;

/**
 * 全てのゲームの基底クラスです.
 * <br>
 * このクラスは主にロジックからの操作を受け取る共通インターフェースとして機能します。<br>
 * <br>
 *
 * @version 1.0.0 - 2013/01/13_23:22:31<br>
 * @author Dra0211<br>
 */
public abstract class Game implements Nameable {

	/** このゲームの名前です. */
	protected final String name;

	/**
	 * 新しいゲームを作成します.
	 * @param name ゲームの名前を指定します。<br>
	 */
	protected Game(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	/**
	 * ゲームの初期化処理を定義します.
	 * このメソッドは、ゲームの起動時（gameStartをコールした後）に必ず1度だけ実行されます。<br>
	 * コンテンツのロードやフィールドの初期化処理を定義してください。<br>
	 */
	protected abstract void startUp();

	/**
	 * ゲームの終了前処理を定義します.
	 * このメソッドは、ウインドウを閉じたり、ゲーム中のイベントによってgameExit()が呼ばれた場合に
	 * 1度だけ実行されます。コンテンツの解放や途中経過の保存を定義してください。<br>
	 */
	protected abstract void dispose();

	/**
	 * ゲームの更新処理を定義します.
	 * このメソッドは、ゲーム実行中のdraw(Graphics2D)がコールされる前に毎回呼ばれます。<br>
	 * ワールドの更新や座標の変更処理を定義してください。<br>
	 */
	protected abstract void update();

	/**
	 * ゲームの再描画を行うメソッドです.
	 * このメソッドは、repaint()メソッドから呼ばれます。このメソッドは、実装によっては
	 * 1フレーム中に何度もコールされることがあります。<br>
	 *
	 * @param g 書き込むグラフィックスコンテキスト.<br>
	 */
	protected abstract void draw(Graphics2D g);

	/**
	 * ゲームループが、再描画処理を要求するために使用するメソッドです.
	 * このメソッドを呼び出すことで、グラフィックスコンテキストを作成し、draw(Graphics2D)を呼び出すように
	 * してください。<br>
	 */
	abstract void repaint();

	/**
	 * このメソッドを呼び出すことで、ゲームを起動します.
	 * このメソッドは、ゲームの起動時に1度だけコールするようにしてください。<br>
	 * 通常は、メインメソッドで必要なシステムプロパティを設定した後、ゲームクラスの
	 * 作成に続いてこのメソッドを呼び出します。<br>
	 * GUIやフィールドの初期化後、ループを起動してください。ループがstartUp()を呼び出すため、<br>
	 * startUp()を明示的に呼び出す必要はありません。<br>
	 *
	 * @param args コマンドライン引数を指定します。<br>
	 *	この値はCMDArgsクラスに登録されます。<br>
	 * @throws IllegalStateException ゲームがすでに起動している場合に投げられます。<br>
	 */
	protected abstract void gameStart(String[] args) throws IllegalStateException;

	/**
	 * このメソッドを呼び出すことで、ゲームを終了します.
	 * ウインドウのクローズイベントやゲーム中のイベントとして
	 * このメソッドをコールすることができます。<br>
	 * このメソッドはdispose()を起動したあと、アプリケーションを終了させます。<br>
	 *
	 * @throws IllegalStateException ゲームがすでに起動している場合に投げられます。<br>
	 */
	public abstract void gameExit() throws IllegalStateException;

	/**
	 * ゲームのGUI設定を取得します.
	 * このメソッドによって返されるWindowインスタンスに操作を行うことで、
	 * ウインドウの状態を変更することができます。<br>
	 *
	 * @return このゲームで使用されているWindowの実装が返されます.<Br>
	 */
	public abstract GameWindow getWindow();

	/**
	 * ゲームの時間管理クラスを取得します.
	 * このメソッドによって返されるGameTimeManagerに操作を行うことで
	 * FPSの変更や経過時間の取得ができます。<br>
	 *
	 * @return このゲームで使用されているGameTimeManagerが返されます.<br>
	 */
	public abstract GameTimeManager getGameTimeManager();

	@Override
	public String toString() {
		return "Game{" + "name=" + name + '}';
	}
}
