using System;
using System.Linq;
using RootMotion.FinalIK;
using UnityEngine;

[Serializable]
public class BipedIKCtrlData : IKCtrlData
{
	public BipedIKCtrlData(IKEffector effector, FBIKChain chain, IKMappingLimb ik_mapping, FullBodyIKCtrl ik_ctrl, Transform tgt_bone, IKEffector sub_effector, bool use_old = false) : base(ik_ctrl, tgt_bone, use_old, false)
	{
		this.Effector = effector;
		this.Effector.target = base.IKTarget;
		this.Chain = chain;
		this.IKMapping = ik_mapping;
		this.RootEffector = sub_effector;
		Transform transform = this.CreateSubTarget("BendBone");
		this.m_BoneBendGoal = new IKCtrlData.BoneTgtPair(this.Chain.bendConstraint.bone2, transform);
		this.Chain.bendConstraint.bendGoal = transform;
		this.Chain.bendConstraint.weight = 1f;
		this.RootEffector.target = this.CreateSubTarget("ChainRootBone");
		this.m_RootBoneTgtPair = new IKCtrlData.BoneTgtPair(this.RootEffector.bone, this.RootEffector.target);
		this.m_ForceIKEnable = true;
		this.ToCorrectBone = base.TargetBone;
	}

	public Transform BendBone
	{
		get
		{
			return this.m_BoneBendGoal.Bone;
		}
	}

	public override Transform[] ChainBones
	{
		get
		{
			return (from node in this.Chain.nodes
			select node.transform).ToArray<Transform>();
		}
	}

	public override float PositionWeight
	{
		get
		{
			return this.Effector.positionWeight;
		}
		set
		{
			this.Effector.positionWeight = value;
		}
	}

	public override float RotationWeight
	{
		get
		{
			return this.Effector.rotationWeight;
		}
		set
		{
			this.Effector.rotationWeight = value;
		}
	}

	private Transform CreateSubTarget(string name)
	{
		Transform transform = base.IKTarget.parent.Find(name);
		if (!transform)
		{
			transform = new GameObject(name).transform;
			transform.SetParent(base.IKTarget.parent, false);
		}
		return transform;
	}

	private void CheckBorder(BipedIKCtrlData.BorderCorrectData correctData)
	{
		if (!correctData.Enable)
		{
			return;
		}
		float num = 0f;
		Vector3 check_pos = this.ToCorrectBone.position + this.MyIKCtrl.BodyCtrlData.BodyOffset;
		if (correctData.CheckBorder(check_pos, ref num))
		{
			switch (this.CorrectType)
			{
			case BipedIKCtrlData.BorderCorrectType.Bone:
				base.IKTarget.position += correctData.Axis * num;
				this.m_BoneBendGoal.Target.position += correctData.Axis * num;
				break;
			case BipedIKCtrlData.BorderCorrectType.HalfBody:
				base.IKTarget.position += correctData.Axis * num;
				this.m_BoneBendGoal.Target.position += correctData.Axis * num;
				this.m_RootBoneTgtPair.Target.position += correctData.Axis * num;
				break;
			case BipedIKCtrlData.BorderCorrectType.Chara:
				if (correctData.GetValue(this.MyIKCtrl.BodyCtrlData.AddOffset) < num)
				{
					this.MyIKCtrl.BodyCtrlData.SetAddOffset(correctData.Axis * num);
				}
				break;
			case BipedIKCtrlData.BorderCorrectType.All:
				if (correctData.GetValue(this.MyIKCtrl.BodyCtrlData.AllOffset) < num)
				{
					this.MyIKCtrl.BodyCtrlData.SetAllOffset(correctData.Axis * num);
				}
				break;
			}
		}
	}

	public override void ApplyIKSetting()
	{
		this.m_BoneBendGoal.Cppy();
		this.m_RootBoneTgtPair.Cppy();
		base.ApplyIKSetting();
		if (base.ForceIK)
		{
			this.CheckBorder(this.WallCorrect);
			this.CheckBorder(this.FloorCorrect);
		}
	}

	public override void Detach(IKCtrlData.IKAttachType attachType, float blend_time = 0f)
	{
		base.Detach(attachType, blend_time);
		this.Chain.bendConstraint.weight = 1f;
		this.RootEffector.positionWeight = 0f;
		this.RootEffector.rotationWeight = 0f;
		this.m_BoneBendGoal.PosOffset = Vector3.zero;
		this.m_RootBoneTgtPair.PosOffset = Vector3.zero;
		this.WallCorrect.Reset();
		this.FloorCorrect.Reset();
		this.ToCorrectBone = base.TargetBone;
		this.CorrectType = BipedIKCtrlData.BorderCorrectType.Bone;
	}

	public override void SetTargetOffset(Vector3 offset, bool inverse = false)
	{
		if (base.IsIKExec)
		{
			return;
		}
		base.SetTargetOffset(offset, inverse);
		this.m_BoneBendGoal.PosOffset = this.m_OffsetEnable.GetEnablePos(offset, inverse);
		this.m_RootBoneTgtPair.PosOffset = this.m_OffsetEnable.GetEnablePos(offset, inverse);
	}

	private IKCtrlData.BoneTgtPair m_BoneBendGoal;

	private IKCtrlData.BoneTgtPair m_RootBoneTgtPair;

	[Header("壁・床補正情報")]
	public BipedIKCtrlData.BorderCorrectData WallCorrect = new BipedIKCtrlData.BorderCorrectData(Vector3.forward);

	public BipedIKCtrlData.BorderCorrectData FloorCorrect = new BipedIKCtrlData.BorderCorrectData(Vector3.up);

	public BipedIKCtrlData.BorderCorrectType CorrectType;

	public Transform ToCorrectBone;

	public readonly IKEffector Effector;

	public readonly FBIKChain Chain;

	public readonly IKMappingLimb IKMapping;

	public readonly IKEffector RootEffector;

	public enum BorderCorrectType
	{
		Bone,
		HalfBody,
		Chara,
		All
	}

	[Serializable]
	public class BorderCorrectData
	{
		public BorderCorrectData(Vector3 axis)
		{
			this.Axis = axis;
		}

		public void Reset()
		{
			this.Border = 0f;
			this.Enable = false;
		}

		public float GetValue(Vector3 pos)
		{
			pos = KasaiUtility.Vec3Multiply(pos, this.Axis);
			return pos.magnitude * Vector3.Dot(this.Axis, pos.normalized);
		}

		public bool CheckBorder(Vector3 check_pos, ref float diff)
		{
			float value = this.GetValue(check_pos);
			diff = this.Border - value;
			return value < this.Border;
		}

		public float Border;

		public bool Enable;

		public Vector3 Axis;
	}
}
