/*!
* @file Coordinates.h
* @brief Coordinatesクラスとその他付随要素の定義
* @date 2014/01/26
* @author Deskull
* 2014 Sikabane Works.
*/

#pragma once

#include "stdafx.h"
#include "Deeangband.h"

namespace Deeangband
{
	typedef std::vector<Coordinates> RANGE_VECTOR;

	//#include "EngineTypedef.h"

	/*! 
	* @class Coordinates
	* @brief ゲーム座標のクラス
	* @details
	* <H1>概要</H1>
	* CoordinatesクラスはFieldによる二次元座標中に配置される各種オブジェクトの座標処理を定義する。
	* <H2>ステータス要素</H2>
	* ゲーム座標は以下のステータス要素を持っている。
	* <ul>
	* <li>X座標/FX</li>
	* <li>Y座標/FY</li>
	* </ul>
	*/
	class Coordinates
	{
	private:
		MAP_POSITION fx; //!< X座標
		MAP_POSITION fy; //!< Y座標

		friend class boost::serialization::access;

		/*!
		* @brief クラスのシリアライズを設定する
		* @param archive アーカイブ化するクラスのアドレス
		* @param version ファイルバージョン
		* @return XMLSerializeテンプレート
		*/
		template<class Archive> void serialize(Archive &archive, const unsigned int version) 
		{
			if(version >= 0)
			{
				archive & boost::serialization::make_nvp("X", fx);
				archive & boost::serialization::make_nvp("Y", fy);
			}
		}

	public:

		/*! 
		 * @brief Coordinatesクラスのコンストラクタ
		 * @param x X座標
		 * @param y Y座標
		 */
		Coordinates::Coordinates(int x, int y);

		/*! 
		 * @brief Coordinatesクラスのコンストラクタ
		 */
		Coordinates::Coordinates(void);

		/*! 
		 * @brief Coordinatesクラスのデストラクタ
		 */
		Coordinates::~Coordinates(void);

		/*
		 * @brief 座標を設定する
		 * @param x X座標
		 * @param y Y座標
		 */
		void Coordinates::Set(int x, int y);

		/*
		 * @brief X座標を得る
		 * @return X座標
		 */
		int Coordinates::GetX(void);

		/*
		 * @brief Y座標を得る
		 * @return Y座標を得る
		 */
		int Coordinates::GetY(void);

		/*!
		 * @brief +演算子による座標代入
		 * @param plus 加算元
		 */
		Coordinates Coordinates::operator=(const Coordinates& plus);  

		/*!
		 * @brief +演算子による座標加算
		 * @param plus 加算元
		 */
		Coordinates Coordinates::operator+(const Coordinates& plus);  

		/*!
		 * @brief +=演算子による座標加算
		 * @param plus 加算元
		 */
		Coordinates& Coordinates::operator+=(const Coordinates& plus);

		/*!
		 * @brief ==演算子による等号判定
		 * @param plus 加算元
		 */
		bool Coordinates::operator==(const Coordinates& plus);

		/*!
		 * @brief 両点の距離計算
		 * @param a 端点1
		 * @param b 端点2
		 * @return 距離
		 */
		static int Coordinates::Distance(Coordinates a, Coordinates b);

		/*!
		 * @brief 両点の距離計算
		 * @param x1 端点1X座標
		 * @param y1 端点1Y座標
		 * @param x2 端点2X座標
		 * @param y2 端点2Y座標
		 * @return 距離
		 */
		static int Coordinates::Distance(int x1, int y1, int x2, int y2);

		/*!
		 * @brief 両点の距離計算
		 * @param a もう一方の端点
		 * @return 距離
		 */
		int Coordinates::Distance(Coordinates a);

		/*!
		 * @brief 矩形範囲取得
		 * @param rangeVec 追加先参照渡し
		 * @param leftTop 範囲左上
		 * @param rightBottom 範囲右下
		 * @return なし
		 */
		void Coordinates::GetRectRange(std::vector<Coordinates> &rangeVec, Coordinates leftTop, Coordinates rightBottom);

		/*!
		 * @brief 矩形範囲取得
		 * @param rangeVec 追加先参照渡し
		 * @param left 左X座標
		 * @param top 上Y座標
		 * @param right 右X座標
		 @ @param bottom 下Y座標
		 * @return なし
		 */
		void Coordinates::GetRectRange(std::vector<Coordinates> &rangeVec, int left, int top, int right, int bottom);

		/*!
		 * @brief 円形範囲取得
		 * @param rangeVec 追加先参照渡し
		 * @param point 範囲中心
		 * @param min 最低範囲
		 * @param max 最大範囲
		 * @return なし
		 */
		static void Coordinates::GetRoundRange(std::vector<Coordinates> &rangeVec, Coordinates point, int min, int max);

		/*!
		 * @brief 円形範囲取得
		 * @param rangeVec 追加先参照渡し
		 * @param px 範囲中心X座標
		 * @param py 範囲中心Y座標
		 * @param min 最低範囲
		 * @param max 最大範囲
		 * @return なし
		 */
		static void Coordinates::GetRoundRange(std::vector<Coordinates> &rangeVec, int px, int py, int min, int max);

		/*!
		 * @brief 円形範囲取得
		 * @param rangeVec 追加先参照渡し
		 * @param min 最低範囲
		 * @param max 最大範囲
		 * @return なし
		 */
		void Coordinates::GetRoundRange(std::vector<Coordinates> &rangeVec, int min, int max);

		/*!
		 * @brief 射線を返す(ブレゼンハム法)
		 * @param rangeVec 追加先参照渡し
		 * @param ax 端点1X座標
		 * @param by 端点1Y座標
		 * @param ax 端点2X座標
		 * @param by 端点2Y座標
		 */
		static void Coordinates::LineOfSight(std::vector<Coordinates> &rangeVec, int x1, int y1, int x2, int y2);
	};

}

BOOST_CLASS_VERSION(Deeangband::Coordinates, 10);
