
using PhysicsBody = FarseerGames.FarseerPhysics.Dynamics.Body;
using PhysicsGeometry = FarseerGames.FarseerPhysics.Collisions.Geom;
using PhysicsVertices = FarseerGames.FarseerPhysics.Collisions.Vertices;
using PhysicsJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.Joint;
using PhysicsAngleJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.AngleJoint;
using PhysicsAngleLimitJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.AngleLimitJoint;
using PhysicsFixedAngleJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.FixedAngleJoint;
using PhysicsFixedAngleLimitJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.FixedAngleLimitJoint;
using PhysicsFixedRevoluteJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.FixedRevoluteJoint;
using PhysicsPinJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.PinJoint;
using PhysicsRevoluteJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.RevoluteJoint;
using PhysicsSliderJoint = FarseerGames.FarseerPhysics.Dynamics.Joints.SliderJoint;
using PhysicsSpring = FarseerGames.FarseerPhysics.Dynamics.Springs.Spring;
using PhysicsAngleSpring = FarseerGames.FarseerPhysics.Dynamics.Springs.AngleSpring;
using PhysicsFixedLinearSpring = FarseerGames.FarseerPhysics.Dynamics.Springs.FixedLinearSpring;
using PhysicsLinearSpring = FarseerGames.FarseerPhysics.Dynamics.Springs.LinearSpring;

namespace XELF.Sphynx {

	static class PhysicsHelper {
		#region Cloneメソッド群

		public static PhysicsBody Clone(this PhysicsBody value) {
			var result = new PhysicsBody();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsGeometry Clone(this PhysicsGeometry value, PhysicsBody body, PhysicsVertices vertices) {
			var result = new PhysicsGeometry(body, vertices, 0);
			//result.SetVertices(vertices); // SetBodyで必要
			//result.SetBody(body); // IsStaticでbodyの参照が必要
			value.CopyTo(result);
			return result;
		}

		public static PhysicsAngleJoint Clone(this PhysicsAngleJoint value) {
			var result = new PhysicsAngleJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsAngleLimitJoint Clone(this PhysicsAngleLimitJoint value) {
			var result = new PhysicsAngleLimitJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsFixedAngleJoint Clone(this PhysicsFixedAngleJoint value) {
			var result = new PhysicsFixedAngleJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsFixedAngleLimitJoint Clone(this PhysicsFixedAngleLimitJoint value) {
			var result = new PhysicsFixedAngleLimitJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsFixedRevoluteJoint Clone(this PhysicsFixedRevoluteJoint value) {
			var result = new PhysicsFixedRevoluteJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsPinJoint Clone(this PhysicsPinJoint value) {
			var result = new PhysicsPinJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsRevoluteJoint Clone(this PhysicsRevoluteJoint value) {
			var result = new PhysicsRevoluteJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsSliderJoint Clone(this PhysicsSliderJoint value) {
			var result = new PhysicsSliderJoint();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsAngleSpring Clone(this PhysicsAngleSpring value) {
			var result = new PhysicsAngleSpring();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsFixedLinearSpring Clone(this PhysicsFixedLinearSpring value) {
			var result = new PhysicsFixedLinearSpring();
			value.CopyTo(result);
			return result;
		}

		public static PhysicsLinearSpring Clone(this PhysicsLinearSpring value) {
			var result = new PhysicsLinearSpring();
			value.CopyTo(result);
			return result;
		}

		#endregion

		#region CopyToメソッド群
		/// <summary>
		/// コピーします。
		/// ただし、Updated, Disposed、処理されません。
		/// Tagは参照になっている可能性があります。
		/// </summary>
		/// <param name="s"></param>
		/// <param name="d"></param>
		public static void CopyTo(this PhysicsBody s, PhysicsBody d) {
			d.AngularVelocity = s.AngularVelocity;
			d.Enabled = s.Enabled;
			d.IdleTime = s.IdleTime;
			d.IsAutoIdle = s.IsAutoIdle;
			d.IsDisposed = s.IsDisposed;
			d.IsQuadraticDragEnabled = s.IsQuadraticDragEnabled;
			d.LinearDragCoefficient = s.LinearDragCoefficient;
			d.LinearVelocity = s.LinearVelocity;
			d.QuadraticDragCoefficient = s.QuadraticDragCoefficient;
			d.RotationalDragCoefficient = s.RotationalDragCoefficient;
			d.Tag = s.Tag; // 参照の可能性あり
			//d.Updated = s.Updated;

			d.Mass = s.Mass;
			d.MomentOfInertia = s.MomentOfInertia;
			d.IsStatic = s.IsStatic;
			d.Position = s.Position;
			d.Rotation = s.Rotation;

			//d.Disposed = s.Diposed;
		}

		/// <summary>
		/// コピーします。
		/// ただし、Body, Vertices, OnCollision, OnSeparationは処理されません。
		/// Tagは参照になっている可能性があります。
		/// </summary>
		/// <param name="s"></param>
		/// <param name="d"></param>
		public static void CopyTo(this PhysicsGeometry s, PhysicsGeometry d) {
			//Body
			//Vertices

			//d.OnCollision = s.OnColision;
			//d.OnSeparation = s.OnSeparation;
			//d.IsSensor = s.IsSensor; // CollisionEnabledが書き換わるので、先に処理。また、Body.IsStaicを書き換えることに注意。
			d.AABB = s.AABB;
			d.CollidesWith = s.CollidesWith;
			d.CollisionCategories = s.CollisionCategories;
			d.CollisionEnabled = s.CollisionEnabled;
			//d.GridCellSize = s.GridCellSize;
			d.CollisionGroup = s.CollisionGroup;
			d.CollisionResponseEnabled = s.CollisionResponseEnabled;
			d.FrictionCoefficient = s.FrictionCoefficient;
			d.Matrix = s.Matrix;
			d.RestitutionCoefficient = s.RestitutionCoefficient;
			d.Tag = s.Tag; // 参照の可能性あり
			//d.IsDisposed = s.IsDisposed;
			d.IsDisposed = false;
			//if (s.IsDisposed) throw new System.ObjectDisposedException("s");
		}

		public static void CopyTo(this PhysicsJoint s, PhysicsJoint d) {
			d.BiasFactor = s.BiasFactor;
			d.Breakpoint = s.Breakpoint;
			//d.Broke = s.Broke;
			d.Enabled = s.Enabled;
			d.Softness = s.Softness;
			d.Tag = s.Tag; // 参照の可能性あり
			d.IsDisposed = s.IsDisposed;
		}

		public static void CopyTo(this PhysicsAngleJoint s, PhysicsAngleJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.MaxImpulse = s.MaxImpulse;
			d.TargetAngle = s.TargetAngle;
		}

		public static void CopyTo(this PhysicsAngleLimitJoint s, PhysicsAngleLimitJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.LowerLimit = s.LowerLimit;
			d.Slop = s.Slop;
			d.UpperLimit = d.UpperLimit;
		}

		public static void CopyTo(this PhysicsFixedAngleJoint s, PhysicsFixedAngleJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.MaxImpulse = s.MaxImpulse;
			d.TargetAngle = s.TargetAngle;
		}

		public static void CopyTo(this PhysicsFixedAngleLimitJoint s, PhysicsFixedAngleLimitJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.LowerLimit = s.LowerLimit;
			d.Slop = s.Slop;
			d.UpperLimit = s.UpperLimit;
		}

		public static void CopyTo(this PhysicsFixedRevoluteJoint s, PhysicsFixedRevoluteJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.Anchor = s.Anchor;
			d.MaxImpulse = s.MaxImpulse;
		}

		public static void CopyTo(this PhysicsPinJoint s, PhysicsPinJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.Anchor1 = s.Anchor1;
			d.Anchor2 = s.Anchor2;
			d.TargetDistance = s.TargetDistance;
		}

		public static void CopyTo(this PhysicsRevoluteJoint s, PhysicsRevoluteJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.Anchor = s.Anchor;
		}

		public static void CopyTo(this PhysicsSliderJoint s, PhysicsSliderJoint d) {
			(d as PhysicsJoint).CopyTo(d);
			d.Anchor1 = s.Anchor1;
			d.Anchor2 = s.Anchor2;
			d.Max = s.Max;
			d.Min = s.Min;
			d.Slop = s.Slop;
		}

		public static void CopyTo(this PhysicsSpring s, PhysicsSpring d) {
			d.Breakpoint = s.Breakpoint;
			d.DampingConstant = s.DampingConstant;
			d.Enabled = s.Enabled;
			d.IsDisposed = s.IsDisposed;
			d.SpringConstant = s.SpringConstant;
			//d.SpringError = s.SpringError;
			d.Tag = s.Tag;
			//d.Broke=s.Broke;
		}

		public static void CopyTo(this PhysicsAngleSpring s, PhysicsAngleSpring d) {
			(s as PhysicsSpring).CopyTo(d);
			d.MaxTorque = s.MaxTorque;
			d.TargetAngle = s.TargetAngle;
			d.TorqueMultiplier = s.TorqueMultiplier;
		}

		public static void CopyTo(this PhysicsFixedLinearSpring s, PhysicsFixedLinearSpring d) {
			(s as PhysicsSpring).CopyTo(d);
			d.BodyAttachPoint = s.BodyAttachPoint;
			d.RestLength = s.RestLength;
			d.WorldAttachPoint=s.WorldAttachPoint;
		}

		public static void CopyTo(this PhysicsLinearSpring s, PhysicsLinearSpring d) {
			(s as PhysicsSpring).CopyTo(d);
			d.AttachPoint1 = s.AttachPoint1;
			d.AttachPoint2 = s.AttachPoint2;
			d.RestLength = s.RestLength;
		}

		#endregion
	}

}
