using System;
using System.Collections.Generic;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Dynamics.Joints;
using FarseerGames.FarseerPhysics.Dynamics.Springs;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace FarseerPhysicsTutorial1 {

	public class Game1 : Microsoft.Xna.Framework.Game {
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;
		Drawer drawer;
		PhysicsSimulator world = new PhysicsSimulator();
		Body groundBody = new Body();
		Geom groundGeom;
		readonly List<Geom> geoms = new List<Geom>();

		Geom AddObject(Vector2 position, float rotation, float mass, Vertices vertices) {
			var body = new Body();
			world.Add(body);
			body.Position = position;
			body.Rotation = rotation;
			vertices.SubDivideEdges(0.5f); // 辺を細分割する。
			var geom = new Geom(body, vertices, 1);
			body.Mass = mass;
			body.MomentOfInertia = mass * vertices.GetMomentOfInertia();
			world.Add(geom);
			geoms.Add(geom);
			return geom;
		}

		public Game1() {
			graphics = new GraphicsDeviceManager(this);
			graphics.PreferMultiSampling = true;
			TargetElapsedTime = TimeSpan.FromSeconds(1.0 / 240);
			Content.RootDirectory = "Content";

			world.Gravity = new Vector2(0, 9.8f);

			// 地面
			{
				world.Add(groundBody);
				groundBody.IsStatic = true;
				var vertices = new Vertices(new Vector2[] {
					new Vector2(-10, +09),
					new Vector2(+10, +09),
					new Vector2(+10, +10),
					new Vector2(-10, +10),
				});
				vertices.SubDivideEdges(0.125f); // 辺を細分割する。
				groundGeom = new Geom(groundBody, vertices, 1);
				groundGeom.FrictionCoefficient = 0.05f;
				world.Add(groundGeom);
			}

			// 4角形の物体
			var geom1 = AddObject(new Vector2(0, 0), 0.1f, 10, new Vertices(new Vector2[] {
				new Vector2(-1, -1),
				new Vector2(+1, -1),
				new Vector2(+1, +1),
				new Vector2(-1, +1),
			}));

			// 5角形の物体
			var geom2 = AddObject(new Vector2(2, 0), 0.2f, 0.1f, new Vertices(new Vector2[] {
				new Vector2(-2, -2),
				new Vector2(+1, -1),
				new Vector2(+1, +0),
				new Vector2(+0, +1),
				new Vector2(-1, +1),
			}));

			// 4角形をワールドに回転関節でつなぐ。
			world.Add(new FixedRevoluteJoint(geom1.Body, new Vector2(0.5f, 0)));
			// 5角形をワールドにバネでつなぐ。
			world.Add(new FixedLinearSpring(geom2.Body, new Vector2(0, 0), new Vector2(0, 0), 3.0f, 0.2f));
		}

		protected override void LoadContent() {
			spriteBatch = new SpriteBatch(GraphicsDevice);
			drawer = new Drawer(GraphicsDevice);
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();

			world.Update((float)gameTime.ElapsedGameTime.TotalSeconds);

			base.Update(gameTime);
		}

		void Draw(Geom geom) {
			drawer.DrawClosedPolyline(geom.WorldVertices.GetVerticesArray());
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);

			var aspectRatio = GraphicsDevice.Viewport.AspectRatio;
			drawer.Begin(Matrix.CreateOrthographicOffCenter(-10 * aspectRatio, 10 * aspectRatio, 10, -10, -10, 10));
			foreach (var geom in geoms)
				Draw(geom);
			Draw(groundGeom);
			drawer.End();

			base.Draw(gameTime);
		}
	}
}
