using System;
using System.Collections;
using System.Linq;
using Assets.CoreScripts;
using Hazel;
using InnerNet;
using PowerTools;
using UnityEngine;

public class PlayerPhysics : InnerNetObject
{
	public float TrueSpeed
	{
		get
		{
			return this.Speed * PlayerControl.GameOptions.PlayerSpeedMod;
		}
	}

	public float TrueGhostSpeed
	{
		get
		{
			return this.GhostSpeed * PlayerControl.GameOptions.PlayerSpeedMod;
		}
	}

	public float Speed = 4.5f;

	public float GhostSpeed = 3f;

	[HideInInspector]
	private Rigidbody2D body;

	[HideInInspector]
	private SpriteAnim Animator;

	[HideInInspector]
	private SpriteRenderer rend;

	[HideInInspector]
	private PlayerControl myPlayer;

	public AnimationClip RunAnim;

	public AnimationClip IdleAnim;

	public AnimationClip GhostIdleAnim;

	public AnimationClip EnterVentAnim;

	public AnimationClip ExitVentAnim;

	public AnimationClip SpawnAnim;

	public SkinLayer Skin;

	public void Awake()
	{
		this.body = base.GetComponent<Rigidbody2D>();
		this.Animator = base.GetComponent<SpriteAnim>();
		this.rend = base.GetComponent<SpriteRenderer>();
		this.myPlayer = base.GetComponent<PlayerControl>();
	}

	private void FixedUpdate()
	{
		this.HandleAnimation();
		if (base.AmOwner && this.myPlayer.CanMove && GameData.Instance)
		{
			DestroyableSingleton<Telemetry>.Instance.WritePosition(this.myPlayer.PlayerId, base.transform.position);
			GameData.PlayerInfo data = this.myPlayer.Data;
			if (data == null)
			{
				return;
			}
			bool isDead = data.IsDead;
			this.body.velocity = DestroyableSingleton<HudManager>.Instance.joystick.Delta * (isDead ? this.TrueGhostSpeed : this.TrueSpeed);
		}
	}

	private void LateUpdate()
	{
		Vector3 position = base.transform.position;
		position.z = position.y / 1000f;
		base.transform.position = position;
	}

	public Vector3 Vec2ToPosition(Vector2 pos)
	{
		return new Vector3(pos.x, pos.y, pos.y / 1000f);
	}

	public void SetSkin(uint skinId)
	{
		this.Skin.SetSkin(skinId);
		if (this.Animator.IsPlaying(this.SpawnAnim))
		{
			this.Skin.SetSpawn(this.Animator.Time);
		}
	}

	public void ResetAnim(bool stopCoroutines = true)
	{
		if (stopCoroutines)
		{
			this.myPlayer.StopAllCoroutines();
			base.StopAllCoroutines();
		}
		base.enabled = true;
		this.myPlayer.inVent = false;
		this.myPlayer.Visible = true;
		GameData.PlayerInfo data = this.myPlayer.Data;
		if (data == null || !data.IsDead)
		{
			this.Skin.SetIdle();
			this.Animator.Play(this.IdleAnim, 1f);
			this.myPlayer.Visible = true;
			this.myPlayer.SetHatAlpha(1f);
			return;
		}
		this.Skin.SetGhost();
		this.Animator.Play(this.GhostIdleAnim, 1f);
		this.myPlayer.SetHatAlpha(0.5f);
	}

	private void HandleAnimation()
	{
		if (this.Animator.IsPlaying(this.SpawnAnim))
		{
			return;
		}
		if (!GameData.Instance)
		{
			return;
		}
		Vector2 velocity = this.body.velocity;
		AnimationClip currentAnimation = this.Animator.GetCurrentAnimation();
		GameData.PlayerInfo data = this.myPlayer.Data;
		if (data == null)
		{
			return;
		}
		if (!data.IsDead)
		{
			if (velocity.sqrMagnitude >= 0.05f)
			{
				if (currentAnimation != this.RunAnim)
				{
					this.Animator.Play(this.RunAnim, 1f);
					this.Skin.SetRun();
				}
				if (velocity.x < -0.01f)
				{
					this.rend.flipX = true;
				}
				else if (velocity.x > 0.01f)
				{
					this.rend.flipX = false;
				}
			}
			else if (currentAnimation == this.RunAnim || currentAnimation == this.SpawnAnim || !currentAnimation)
			{
				this.Skin.SetIdle();
				this.Animator.Play(this.IdleAnim, 1f);
				this.myPlayer.SetHatAlpha(1f);
			}
		}
		else
		{
			this.Skin.SetGhost();
			if (currentAnimation != this.GhostIdleAnim)
			{
				this.Animator.Play(this.GhostIdleAnim, 1f);
				this.myPlayer.SetHatAlpha(0.5f);
			}
			if (velocity.x < -0.01f)
			{
				this.rend.flipX = true;
			}
			else if (velocity.x > 0.01f)
			{
				this.rend.flipX = false;
			}
		}
		this.Skin.Flipped = this.rend.flipX;
	}

	public IEnumerator CoSpawnPlayer(LobbyBehaviour lobby)
	{
		if (!lobby)
		{
			yield break;
		}
		Vector3 spawnPos = this.Vec2ToPosition(lobby.SpawnPositions[(int)this.myPlayer.PlayerId % lobby.SpawnPositions.Length]);
		this.myPlayer.nameText.gameObject.SetActive(false);
		this.myPlayer.Collider.enabled = false;
		KillAnimation.SetMovement(this.myPlayer, false);
		bool amFlipped = this.myPlayer.PlayerId > 4;
		this.myPlayer.GetComponent<SpriteRenderer>().flipX = amFlipped;
		this.myPlayer.transform.position = spawnPos;
		SoundManager.Instance.PlaySound(lobby.SpawnSound, false, 1f).volume = 0.75f;
		this.Skin.SetSpawn(0f);
		this.Skin.Flipped = this.rend.flipX;
		yield return new WaitForAnimationFinish(this.Animator, this.SpawnAnim);
		base.transform.position = spawnPos + new Vector3(amFlipped ? -0.3f : 0.3f, -0.24f);
		this.ResetAnim(false);
		Vector2 b = (-spawnPos).normalized;
		yield return this.WalkPlayerTo((Vector2)spawnPos + b, 0.01f);
		this.myPlayer.Collider.enabled = true;
		KillAnimation.SetMovement(this.myPlayer, true);
		this.myPlayer.nameText.gameObject.SetActive(true);
		yield break;
	}

	public void ExitAllVents()
	{
		this.ResetAnim(true);
		this.myPlayer.moveable = true;
		Vent[] allVents = ShipStatus.Instance.AllVents;
		for (int i = 0; i < allVents.Length; i++)
		{
			allVents[i].SetButtons(false);
		}
	}

	private IEnumerator CoEnterVent(int id)
	{
		Vent vent = ShipStatus.Instance.AllVents.First((Vent v) => v.Id == id);
		this.myPlayer.moveable = false;
		yield return this.WalkPlayerTo(vent.transform.position, 0.01f);
		vent.EnterVent();
		this.Skin.SetEnterVent();
		yield return new WaitForAnimationFinish(this.Animator, this.EnterVentAnim);
		this.Skin.SetIdle();
		this.Animator.Play(this.IdleAnim, 1f);
		this.myPlayer.Visible = false;
		this.myPlayer.inVent = true;
		yield break;
	}

	private IEnumerator CoExitVent(int id)
	{
		Vent vent = ShipStatus.Instance.AllVents.First((Vent v) => v.Id == id);
		this.myPlayer.Visible = true;
		this.myPlayer.inVent = false;
		vent.ExitVent();
		this.Skin.SetExitVent();
		yield return new WaitForAnimationFinish(this.Animator, this.ExitVentAnim);
		this.Skin.SetIdle();
		this.Animator.Play(this.IdleAnim, 1f);
		this.myPlayer.moveable = true;
		yield break;
	}

    // 移动位置
	public IEnumerator WalkPlayerTo(Vector2 worldPos, float tolerance = 0.01f)
	{
		worldPos -= base.GetComponent<CircleCollider2D>().offset;
		Rigidbody2D body = this.body;
		do
		{
			Vector2 vector2;
			Vector2 vector = vector2 = worldPos - (Vector2)base.transform.position;
			if (vector2.sqrMagnitude <= tolerance)
			{
				break;
			}
			float d = Mathf.Clamp(vector.magnitude * 2f, 0.01f, 1f);
			body.velocity = vector.normalized * this.Speed * d;
			yield return null;
		}
		while (body.velocity.magnitude >= 0.0001f);
		body.velocity = Vector2.zero;
		yield break;
	}

    // 无同步数据
	public override bool Serialize(MessageWriter writer, bool initialState)
	{
		return false;
	}

	public override void Deserialize(MessageReader reader, bool initialState)
	{
	}


    public void RpcEnterVent(int id)
	{
		if (AmongUsClient.Instance.AmClient)
		{
			base.StartCoroutine(this.CoEnterVent(id));
		}
		MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.Reliable);
		messageWriter.WritePacked(id);
		messageWriter.EndMessage();
	}

	public void RpcExitVent(int id)
	{
		if (AmongUsClient.Instance.AmClient)
		{
			base.StartCoroutine(this.CoExitVent(id));
		}
		MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 1, SendOption.Reliable);
		messageWriter.WritePacked(id);
		messageWriter.EndMessage();
	}

    private enum RpcCalls
    {
        EnterVent,
        ExitVent
    }

    public override void HandleRpc(byte callId, MessageReader reader)
	{
		if (callId == 0)
		{
			int id = reader.ReadPackedInt32();
			base.StartCoroutine(this.CoEnterVent(id));
			return;
		}
		if (callId != 1)
		{
			return;
		}
		int id2 = reader.ReadPackedInt32();
		base.StartCoroutine(this.CoExitVent(id2));
	}
}