using System;
using System.Collections.Generic;
using System.Text;
using DxLibDLL;
using Box2DX.Collision;
using Box2DX.Common;
using Box2DX.Dynamics;
using System.Collections;

namespace Nlgp1.B2DX.Test
{
	internal class Gamemain
	{


		static void Main()//Mainにするとこちらがコンパイルできる
		{
			try
			{
				DX.SetWindowSize(512, 384);
				DX.ChangeWindowMode(true);
				DX.SetAlwaysRunFlag(false);
				DX.DxLib_Init();



				//画像読み込み
				DX.Graph mech;
				const float pi = (float)(System.Math.PI);

				mech = DX.LoadGraph("mech.png");

				AABB worldBox = new AABB();
				//左上座標の定義
				worldBox.LowerBound = new Vec2(0, 0);
				//右下座標の定義
				worldBox.UpperBound = new Vec2(500, 400);
				//重力の定義
				Vec2 grav = new Vec2(0, 0);

				World world = new World(worldBox, grav, false);
				DebugDraw dd = new Debug();
				dd.AppendFlags(DebugDraw.DrawFlags.Shape);
				world.SetDebugDraw(dd);
				
				world.SetContactListener(new ContactEvent());


				Vec2[] gravAr = new Vec2[]
				{
					new Vec2(0, -18),
					new Vec2(18, 0),
					new Vec2(-18,0),
					new Vec2(0,18)
				};

				bool keyflag = false;
				//サイズは半径で設定する
				//todo IBoxインターフェイスからIBox.MakeShapeとか呼びだして、構成すれば処理を分けられるはず
				DynamicRigid d = new DynamicRigid(new Vec2(42, 170), 0 * pi / 180, world, 16, 16, false,
					new Dictionary<UserDataKind, string>() 
					{ 
					{ UserDataKind.Name, "player" },
					{ UserDataKind.CategoryBits,"111" },
					{UserDataKind.MaskBits,"111"},
					{UserDataKind.GroupIndex,"10"}
					},
					new Dictionary<ObjectDataKind,float>(),
					true);
				StaticRigid s = new StaticRigid(new Vec2(240, 202), 0, world, 16, 16, true, new Dictionary<UserDataKind, string>() { { UserDataKind.Name, "enemy" }, { UserDataKind.Filter, "111" } }
					,false);
				StaticRigid wall = new StaticRigid(new Vec2(250, 16), 0, world, 250, 16, true,
					new Dictionary<UserDataKind, string>()
					{
					{ UserDataKind.Name, "wall" },
					{ UserDataKind.Filter, "110" },
					{UserDataKind.GroupIndex,"1"}
					}
					,false);
				StaticRigid floor = new StaticRigid(new Vec2(500, 168), 0, world, 16, 150, true,
					new Dictionary<UserDataKind, string>()
					{
					{ UserDataKind.Name, "floor" },  
					{ UserDataKind.Filter, "101" }
					}
					,false);

				//dに新しいボディを定義する
				//最初にこれ以上新しいボディは作らないと宣言する、さもないとボディは作られない
				d.Alregene = false;
				float friction = 0, density = 2, restitution = 0;
				Polygondef2 p2 = new Polygondef2(friction, restitution, density,new myUserData());
				p2.SetAsBox(3, 3, new Vec2(20, 1), 0);
				d.Addtolist(p2);
				d.MakeBody(world);

				//自キャラとの距離を固定する
				//Joints joints = new Joints(d.SelfBody, s.SelfBody);
				//world.CreateJoint(joints.MakeDistanceJoint());

				//ObjectDataKindのAngularDampingは無視されます
				float angularDamping = 0.3f, lineardamping = 0.5f, fric2 = 0.4f, rest2 = 2f, dens2 = 1;
				FilterData f=new FilterData();
				f.CategoryBits = 1;
				f.GroupIndex = 1; f.MaskBits = 1;
				DynamicRigid d2 = new DynamicRigid(new Vec2(50, 60), 0 * pi / 180, lineardamping, angularDamping);
				d2.SetAsBox(16, 16, new Polygondef2(fric2, rest2, dens2, new myUserData("d2", 1, f, 2)), false);
				Polygondef2 d2p = new Polygondef2(friction, restitution, density, new myUserData("d2p", 3, f, 2));
				d2p.SetAsBox(24, 12, new Vec2(-20, 1), 0);
				d2p.Fil();
				
				d2.Addtolist(d2p);
				d2.NoRotate = false;
				d2.MakeBody(world);

				DynamicRigid c1 = new DynamicRigid(new Vec2(300, 90), 0, 0, 0);
				c1.SetAsCircle(new CircleDef2(new Vec2(), 20, 0, 0, 1, new myUserData()), false);
				c1.MakeBody(world);

				DX.SetDrawScreen(DX.DX_SCREEN_BACK);

				//todo GetNameAndIdとかやりたい,worldを継承？
				//GetNameAndId(); --> Dic<int,string> {{1,"player"},{2,"wall"}}
				//GetName(2); -->"player"
				//GetIdArr("enemy"); -->["1","4"] 

				while (DX.ProcessMessage())
				{
					c1.ApplyImpulse(new Vec2(3, 0));
					//List<Shape> shape = d2.Shapelist;
					//このインデックスをSetFilterに渡す
					//Shape.GetBody().GetUserData();がユーザーデータ
					//Shape.Get
					f.MaskBits=1;
					d2.SetFilter(f, 1);

					if (DX.CheckHitKey(DX.KEY_INPUT.RETURN) && !keyflag)
					{
						//瞬間的にある方向に力を加える（270度が設定されているのでオブジェクトから見て真上へ）
						d.ApplyImpulse(new Vec2(0, -990));
					}

					if (!DX.CheckHitKey(DX.KEY_INPUT.RETURN))
					{
						keyflag = false;
					}

					if (DX.CheckHitKey(DX.KEY_INPUT.LEFT))
					{
						d.ApplyRelativeImpulse(new Vec2(-3 * d.Mass, 0),90);
						//d.SelfBody.ApplyTorque(20*d.SelfBody.GetMass());
					}
					DX.ClearDrawScreen();
					DX.ProcessActKeyInput();
					DX.DrawString(2, 7, world.Gravity.X.ToString(), new DX.COLOR_U8(0xffffff));
					DX.DrawString(2, 27, world.Gravity.Y.ToString(), new DX.COLOR_U8(0xffffff));
					
					DX.DrawRotaGraph((int)d.Position.X, (int)d.Position.Y, 1, d.Angle, mech, true, true);
					DX.DrawRotaGraph((int)s.Position.X, (int)s.Position.Y, 1, s.Angle, mech, false);
					
					//試しのRaycast,自分の下から30から10だけ下に光を伸ばす
					d2.color = Colors.Red;
					Shape[] hit = d2.Raycast(new Vec2(0, 30), new Vec2(0, 50));
					world.Step(1 / 60f, 8, 1);
					
					DX.ScreenFlip();
				} DX.DxLib_End();
			} catch (Exception e)
			{
				System.Console.Write(e.ToString());
				throw;
			}
		}


	}
}
