using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Box2DX.Common;
using DxLibDLL;
using Nlgp1.Characters;
using Nlgp1.Common;
using Nlgp1.Sprites;
using Nlgp1.Stages;
using Nlgp1.Utilities;

// [重要]このコードは、暫定版であり実験用コードを含みます。将来的に設計・実装が変更されます。
// これらのコードを生放送等で配信することは、構いませんが実装者の許可無く無断で
// 放送等で晒し目的で利用することを禁止します。改変・改良は、構いません。
// 不満点があれば、開発者に直接伝達を行うか各自で修正を行い、その理由をコメント等で明記して下さい。

namespace Nlgp1.Drawers {
	/// <summary>
	/// ステージ描画クラス
	/// (画面の描画を行う)
	/// </summary>
	public static class StageDrawer {
		/// <summary>
		/// 1画面に表示できるプレーヤーを中心としたチップの数
		/// 例( 8 なら プレーヤーを中心として上下・左右に8チップずつ表示する )
		/// </summary>
		public const int ViewCellCountX = 8;
		/// <summary>
		/// 1画面に表示できるプレーヤーを中心としたチップの数
		/// 例( 8 なら プレーヤーを中心として上下・左右に8チップずつ表示する )
		/// </summary>
		public const int ViewCellCountY = 6;
		// 画面内のプレーヤーの表示位置
		private const float ScrollParameterX = 8 * ChipImage.SizeSide;
		private const float ScrollParameterY = 6 * ChipImage.SizeSide;
		// 描画されるチップの範囲を表す
		private static float xStart = 0;
		private static float yStart = 0;
		private static float xEnd   = 0;
		private static float yEnd   = 0;

		/// <summary>
		/// 横方向のスクロール量
		/// </summary>
		private static float scrollX = 0;
		/// <summary>
		/// 縦方向のスクロール量
		/// </summary>
		private static float scrollY = 0;

		/// <summary>
		/// ステージを読み込みます。
		/// </summary>
		/// <param name="chipCount">チップ数</param>
		public static void LoadStage( int cellCount ) {
			SpriteDrawer.LoadStage( cellCount );
		}

		/// <summary>
		/// ステージを描画します。
		/// </summary>
		public static void Draw() {
			SpriteDrawer player = Stage.PlayerDrawer;
			IEnumerable< SpriteDrawer > drawers = SpriteDrawer.GetCollection();
			scrollX -= player.Location.X;
			if( scrollX < player.Location.X - ScrollParameterX )
				scrollX = player.Location.X - ScrollParameterX;

			scrollY -= player.Location.Y;
			if( scrollY < player.Location.Y - ScrollParameterY )
				scrollY = player.Location.Y - ScrollParameterY;

			#region 可視範囲内でマップの描画
			float chipX  = player.Location.X / ChipImage.SizeSide;
			float chipY  = player.Location.Y / ChipImage.SizeSide;

			xStart = chipX - ViewCellCountX; // 画面左端にスペースができるのでその分のチップを多めに描画する
			yStart = chipY - ViewCellCountY;
			xEnd = chipX + ViewCellCountX;
			yEnd = chipY + ViewCellCountY;

			#endregion

			#region オブジェクトの描画
			foreach( var drawable in drawers )
				if( IsVisibleCell( drawable.Location.X , drawable.Location.Y ) )
					drawable.Draw( new Vec2( drawable.Location.X - scrollX - ChipImage.SizeSide / 2.0f , drawable.Location.Y - scrollY - ChipImage.SizeSide / 2.0f ) );
			#endregion
		}

		/// <summary>
		/// 指定されたピクチップ単位の座標が描画されるべき範囲にあるかどうかを取得します。
		/// </summary>
		/// <param name="row">ピクチップ単位で表されるX座標</param>
		/// <param name="column">ピクチップ単位で表されるY座標</param>
		/// <param name="blankCells">許容する描画範囲外のチップ数</param>
		/// <returns>描画範囲かどうか</returns>
		public static bool IsVisibleCell( float x , float y ) {
			float chipX  = x / ChipImage.SizeSide;
			float chipY  = y / ChipImage.SizeSide;
			return xStart <= chipX && xEnd >= chipX && yStart <= chipY && yEnd >= chipY;
		}
	}
}
