#region HeadComments
/* ========================================================================
* Copyright (C) 2015 ArthunGame
*
* 作    者：Arthun
* 文件名称：RoleController
* 功    能：角色控制器
* 创建时间：2016/01/30 00:12:32
* 
* =========================================================================
*/
#endregion

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 角色动作状态
/// </summary>
public enum RoleAniState
{
    STAND,//0站立
    RUN,//1跑步
    JUMP_BEGGIN,//2跳跃开始
    JUMP_DOWN,//3跳跃下落
    JUMP_END,//4跳跃结束
    DEATH,//5死亡
    SACRIFICE,//6牺牲 变成方块才叫牺牲
    WARSHOP,//7祭拜
}

/// <summary>
/// 角色类型
/// </summary>
public enum RoleType
{
    NONE,//啥也不是
    PLAYER,//玩家
    FOLLOWPLAYER,//跟随玩家
}

[RequireComponent(typeof(CharacterController))]
public class RoleController : MonoBehaviour
{
    public AudioClip walking;//走路
    public AudioClip altarUP;//祭坛升起
    public AudioClip changeRole;//变身方块
    public AudioClip death;//死亡
    public AudioClip doorOpen;//石门打开
    public AudioClip eatCube;//吃方块
    public AudioClip eatCubeEffect;//吃方块声音
    public AudioClip jumpEnd;//跳跃结束

    private AudioSource s_walking;//走路
    private AudioSource s_altarUP;//祭坛升起
    private AudioSource s_changeRole;//变身方块
    private AudioSource s_death;//死亡
    private AudioSource s_doorOpen;//石门打开
    private AudioSource s_eatCube;//吃方块
    private AudioSource s_eatCubeEffect;//吃方块声音
    private AudioSource s_jumpEnd;//跳跃结束

    [HideInInspector]//跟随目标(AI使用)
    public RoleController _FollowTarget;

    [HideInInspector]//AI保持距离
    public float _AIKeepDis = 4f;

    [HideInInspector]//角色ID
    public int _roleID;

    [HideInInspector]//是否可以控制
    public bool _IsControll = true;

    /// <summary>
    /// 死亡回调
    /// </summary>
    /// <param name="role"></param>
    public delegate void OnDeathCallback(RoleController role);
    public OnDeathCallback _OnDeathCallback;

    public Transform _ModelRoot;
    public float _Gravity = 20f;//重力
    public float _RunSpeed = 0f;//移动速度
    public float _JumpForce = 10f;//跳跃力

    private float _VerticalSpeed = 0f;//垂直速度

    private RoleAniState _RoleAniState;//角色动作状态
    public Animation _RoleAni;//角色动作
    private CharacterController _CharacterController;//角色控制器
    private RoleType _RoleType = RoleType.NONE;//人物类型

    private GameObject _SoulBoxEffect;//灵魂箱子特效
    private GameObject _SoulBox;//灵魂箱子

    //private Vector3 _lastEffectivePos = Vector3.zero;//最后一次有效位置
	private Vector3 lastAngle;

    private bool _isChangeForCube = false;
    private bool _IsUseGravity = false;
    private bool isGrounded = false;

    private bool isTriggerGround = false;
    private bool isAltar = false;
    private bool isMoveAltarObj = false;

    private Vector3 AltarPos0 = Vector3.zero;
    private Vector3 AltarPos1 = Vector3.zero;

    private int AltarType = 0;//0召唤房子的神像  1第一个神像 2第二个神像

    private float altatDis = 0f;


    public RoleAniState GetRoleAniState()
    {
        return _RoleAniState;
    }

    void Awake()
    {
        // _RoleAni = this.GetComponent<Animation>();
        _CharacterController = this.GetComponent<CharacterController>();

        _RoleAniState = RoleAniState.STAND;
    }

    void Start()
    {
        _SoulBox = (GameObject)Instantiate(Resources.Load("Prefab/ChangeToCube/PersionCube"));
        _SoulBox.SetActive(false);

        _SoulBoxEffect = (GameObject)Instantiate(Resources.Load("Prefab/ChangeToCube/Effect"));
        _SoulBoxEffect.SetActive(false);
		lastAngle = transform.forward;

        initialAudio();
    }

    void initialAudio()
    {
        s_walking = this.gameObject.AddComponent<AudioSource>();//走路
        s_altarUP = this.gameObject.AddComponent<AudioSource>();//祭坛升起
        s_changeRole = this.gameObject.AddComponent<AudioSource>();//变身方块
        s_death = this.gameObject.AddComponent<AudioSource>();//死亡
        s_doorOpen = this.gameObject.AddComponent<AudioSource>();//石门打开
        s_eatCube = this.gameObject.AddComponent<AudioSource>();//吃方块
        s_eatCubeEffect = this.gameObject.AddComponent<AudioSource>();//吃方块声音
        s_jumpEnd = this.gameObject.AddComponent<AudioSource>();//跳跃结束

        s_walking.clip = walking;
        s_altarUP.clip = altarUP;//祭坛升起
        s_changeRole.clip = changeRole;//变身方块
        s_death.clip = death;//死亡
        s_doorOpen.clip = doorOpen;//石门打开
        s_eatCube.clip = eatCube;//吃方块
        s_eatCubeEffect.clip = eatCubeEffect;//吃方块声音
        s_jumpEnd.clip = jumpEnd;//跳跃结束
    }

    public void InitialRole(RoleType type, int roleID)
    {
        _roleID = roleID;
        _RoleType = type;

        switch (_RoleType)
        {
            case RoleType.PLAYER:
                {
                    CameraController.GetInstance()._Target = this.transform;
                    break;
                }

            case RoleType.FOLLOWPLAYER:
                {
                    break;
                }
        }
    }

    void Update()
    {
        AIFollowUpdate();
        inputOtherUpdate();
        applyGravity();
        applyMove();

        //_RoleAni.SetInteger("state", (int)_RoleAniState);
        //_RoleAni.SetBool("IsGround", _CharacterController.isGrounded);

        if (isAltar && isMoveAltarObj)
        {
            AltarPos0.y += Time.deltaTime * 8f;
            if (Vector3.Distance(AltarPos0, AltarPos1) > altatDis)
            {
                switch (AltarType)
                {
                    case 0:
                        GameLayoutInstance.GetInstance()._AltarObj.position = Vector3.zero;
                        break;

                    case 1:
                        GameLayoutInstance.GetInstance()._door1.position = new Vector3(0f, -20f, 0f);
                        break;

                    case 2:
                        GameLayoutInstance.GetInstance()._door2.position = new Vector3(0f, -20f, 0f);
                        break;
                }

                
                isAltar = false;
                isMoveAltarObj = false;
            }
            else
            {
                switch (AltarType)
                {
                    case 0:
                        GameLayoutInstance.GetInstance()._AltarObj.position = AltarPos0;
                        break;

                    case 1:
                        GameLayoutInstance.GetInstance()._door1.position = AltarPos0;
                        break;

                    case 2:
                        GameLayoutInstance.GetInstance()._door2.position = AltarPos0;
                        break;
                }

            }
        }
    }

   
    void inputOtherUpdate()
    {
        if (_IsControll && _RoleType == RoleType.PLAYER && Input.GetMouseButton(0) && !_isChangeForCube)
        {
            _isChangeForCube = true;
            _IsUseGravity = true;
            SetRoleAni(RoleAniState.SACRIFICE);

            StartCoroutine(ssdffsdfdssdf());
            StartCoroutine(delayDown(0.2f));
            var sc = CameraController.GetInstance().gameObject.AddComponent<SwitchCamera>();
            sc.SetShakeCamera(1.2f, 0.8f, OnSacrifice);
        }
    }

    IEnumerator ssdffsdfdssdf()
    {
        yield return new WaitForSeconds(0.8f);
        if (!s_changeRole.isPlaying)
            s_changeRole.Play();
    }

    IEnumerator delayDown(float time)
    {
        yield return new WaitForSeconds(time);
        _IsUseGravity = false;
    }

    void OnSacrifice()
    {
        GameObject cube = Instantiate(_SoulBox);
        GameObject cubeEffect = Instantiate(_SoulBoxEffect);
        cubeEffect.transform.parent = cube.transform;

        cube.transform.position = this.transform.position + Vector3.up * 1.1f;
        cube.transform.rotation = this.transform.rotation;
        cube.transform.localScale = Vector3.one;
        cube.SetActive(true);
        cubeEffect.SetActive(true);

        CameraController.GetInstance()._isLookTarget = true;
        _IsControll = false;

        Destroy(this.gameObject);
        Destroy(_SoulBox);
        Destroy(_SoulBoxEffect);

        if (_OnDeathCallback != null)
            _OnDeathCallback(this);
    }

    void applyGravity()
    {
        if (_IsControll || _IsUseGravity)
        {
            if (isGrounded)
            {
				if(_RoleAni.IsPlaying("jump_begin") || _RoleAni.IsPlaying("jump_end")) {
					_RoleAni.Play("idle");
                    _RoleAniState = RoleAniState.STAND;
				}
			
                if (!CameraController.GetInstance()._isLookTarget)
                {
                    //如果当前在地面上则清除之前的移动轨迹
                    //GameLayoutInstance.GetInstance()._LastEffectivePos.Clear();
                    GameLayoutInstance.GetInstance()._delayTime.Clear();
                    GameLayoutInstance.GetInstance()._CameraRecordPosList.Clear();
                    GameLayoutInstance.GetInstance()._RoleRecordPosList.Clear();
                    GameLayoutInstance.GetInstance()._LastEffectivePos.Add(this.transform.position);
                }

                _VerticalSpeed = 0f;

                switch (_RoleType)
                {
                    case RoleType.PLAYER:
                        {
                            //只有在地面时才能跳跃
                            if (Input.GetButton("Jump"))
                            {
                                SetRoleAni(RoleAniState.JUMP_BEGGIN);
                                _VerticalSpeed = _JumpForce;
                            }
                            break;
                        }

                    case RoleType.FOLLOWPLAYER:
                        {
                            break;
                        }
                }
            }
            else
            {
                if (!CameraController.GetInstance()._isLookTarget)
                {  //记录移动轨迹
                    GameLayoutInstance.GetInstance()._delayTime.Add(Time.deltaTime);
                    GameLayoutInstance.GetInstance()._CameraRecordPosList.Add(CameraController.GetInstance().transform.position);
                    GameLayoutInstance.GetInstance()._RoleRecordPosList.Add(this.transform.position);
                }

                _VerticalSpeed -= _Gravity * Time.deltaTime;

                if (_RoleAniState == RoleAniState.JUMP_BEGGIN && (!_RoleAni.IsPlaying("jump_begin") && !_RoleAni.IsPlaying("jump_down")))
                {
                    //射线检测距离
                    _RoleAni.Play("jump_down");
                    _RoleAniState = RoleAniState.JUMP_DOWN;
                }
                else if (_RoleAniState == RoleAniState.JUMP_DOWN && !_RoleAni.IsPlaying("jump_down"))
                {
                    if (!s_jumpEnd.isPlaying)
                        s_jumpEnd.Play();

                    _RoleAni.Play("jump_end");
                    _RoleAniState = RoleAniState.JUMP_END;
                }
            }
        }
    }

    void applyMove()
    {
        if(_IsUseGravity)
        {
            Vector3 mMoveDir = transform.rotation * Vector3.zero + new Vector3(0f, _VerticalSpeed, 0f);
            _CharacterController.Move(mMoveDir);
            return;

        }

        if (_RoleAniState == RoleAniState.WARSHOP && !_RoleAni.IsPlaying("warshop_normal"))
            _IsControll = true;

        if (!_IsControll)
            return;

        Vector3 vDir = Vector3.zero;
        switch (_RoleType)
        {
            case RoleType.PLAYER:
                {
                    vDir.x += _RunSpeed * Input.GetAxis("Horizontal");
                    vDir.z += _RunSpeed * Input.GetAxis("Vertical");

                    //if (vDir != Vector3.zero)
                    //    _ModelRoot.localRotation = Quaternion.Euler(new Vector3(0f, getInputDirAngle(), 0f));
					UpdateBodyAngle(vDir);	
						
                    vDir = vDir * Time.deltaTime;
                    break;
                }

            case RoleType.FOLLOWPLAYER:
                {
                    break;
                }
        }

        if (vDir != Vector3.zero)
        {
            if (!s_walking.isPlaying)
                s_walking.Play();
            s_walking.pitch = 1.5f;
            SetRoleAni(RoleAniState.RUN);

            ////跳跃时可以旋转相机但是不能旋转人物
            //if (_CharacterController.isGrounded)
            //{
            //    //根据相机旋转得到角色正确的移动方向
            //    transform.rotation = Quaternion.Euler(new Vector3(0f, CameraController.GetInstance()._X, 0f));
            //}

            //根据相机旋转得到角色正确的移动方向
            transform.rotation = Quaternion.Euler(new Vector3(0f, CameraController.GetInstance()._X, 0f));
        }
        else
        {
            if (_RoleAniState == RoleAniState.WARSHOP)
                return;
            SetRoleAni(RoleAniState.STAND);
        }

        switch (_RoleType)
        {
            case RoleType.PLAYER:
                {
                  
                    Vector3 mMoveDir = transform.rotation * vDir + new Vector3(0f, _VerticalSpeed, 0f);
                    _CharacterController.Move(mMoveDir);
                    isGrounded = GroundCheck();
                    break;
                }

            case RoleType.FOLLOWPLAYER:
                {
                    break;
                }
        }
    }


    private bool GroundCheck()
    {
        RaycastHit hit;
        Debug.DrawLine(transform.position + Vector3.up * 0.1f, transform.position + Vector3.up * -0.3f);

        bool isHit = Physics.Raycast(transform.position + Vector3.up * 0.1f, Vector3.up * -1, out hit, 0.4f);
        if (!isHit)
            return false;

        return Vector3.Dot(hit.normal, Vector3.up) > 0.15f;
    }

    private void UpdateBodyAngle(Vector3 dir) {
		Vector3 newDir = dir == Vector3.zero ? lastAngle : dir;
		lastAngle = newDir;
		
		
		_ModelRoot.localRotation = Quaternion.Lerp(_ModelRoot.localRotation, Quaternion.LookRotation(dir), 6*Time.deltaTime);
		
	}

    float getInputDirAngle()
    {
        float currentAngle = 0f;
        if (Input.GetKey(KeyCode.W))//前
            currentAngle = 0f;

        if (Input.GetKey(KeyCode.D))//后
            currentAngle = 90f;

        if (Input.GetKey(KeyCode.A))//左
            currentAngle = -90f;

        if (Input.GetKey(KeyCode.S))//右
            currentAngle = 180f;

        if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))//左前
            currentAngle = -45f;

        if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D))//右前
            currentAngle = 45f;

        if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.A))//左后
            currentAngle = -135f;

        if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D))//右后
            currentAngle = 135f;








        if (Input.GetKey(KeyCode.UpArrow))//前
            currentAngle = 0f;

        if (Input.GetKey(KeyCode.RightArrow))//右
            currentAngle = 90f;

        if (Input.GetKey(KeyCode.LeftArrow))//左
            currentAngle = -90f;

        if (Input.GetKey(KeyCode.DownArrow))//后
            currentAngle = 180f;

        if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftArrow))//左前
            currentAngle = -45f;

        if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.RightArrow))//右前
            currentAngle = 45f;

        if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftArrow))//左后
            currentAngle = -135f;

        if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.RightArrow))//右后
            currentAngle = 135f;


        return currentAngle;
    }

    /// <summary>
    /// 获取前进方向
    /// </summary>
    /// <returns></returns>
    public Vector3 GetForwardDir()
    {
        Vector3 vDir = Vector3.zero;
        vDir.z += _RunSpeed * 1f;
        return vDir;
    }

    public void Move(Vector3 dir)
    {
        if (_FollowTarget == null)
            return;

        _VerticalSpeed -= _Gravity * Time.deltaTime;
        dir = GetForwardDir() + (this.transform.rotation * dir);
        dir = dir * Time.deltaTime;
        //this.transform.LookAt(lookTarget);
        Vector3 thisPos = this.transform.position;
        thisPos.y = _FollowTarget.transform.position.y;
        this.transform.rotation = Quaternion.LookRotation(_FollowTarget.transform.position - thisPos);

        if (_FollowTarget.GetRoleAniState() == RoleAniState.STAND)
        {
            SetRoleAni(RoleAniState.STAND);
        }
        else
        {
            SetRoleAni(RoleAniState.RUN);
        }

        if (Vector3.Distance(this.transform.position, _FollowTarget.transform.position) > _AIKeepDis)
        {
            Vector3 mMoveDir = transform.rotation * dir + new Vector3(0f, _VerticalSpeed, 0f);
            _CharacterController.Move(mMoveDir);
        }
    }

    public void AIFollowUpdate()
    {
        if (_RoleType != RoleType.FOLLOWPLAYER)
            return;

    }

    public void SetRoleAni(RoleAniState state)
    {
        switch (state)
        {
            case RoleAniState.STAND:
                _IsControll = _RoleType != RoleType.FOLLOWPLAYER;
                if (_RoleAniState != RoleAniState.JUMP_BEGGIN)
                {
                    if (!_RoleAni.IsPlaying("jump_end"))
                    {
                        _RoleAni.Play("idle");
                        _RoleAniState = RoleAniState.STAND;
                    }
                }
                break;

            case RoleAniState.RUN:
                _IsControll = _RoleType != RoleType.FOLLOWPLAYER;

                if (_RoleAniState != RoleAniState.JUMP_BEGGIN)
                {
                    if (!_RoleAni.IsPlaying("jump_end") && !_RoleAni.IsPlaying("run"))
                    {
                        _RoleAni["run"].speed = 2.5f;
                        _RoleAni.Play("run");
                        _RoleAniState = RoleAniState.RUN;
                    }
                }
                break;

            case RoleAniState.JUMP_BEGGIN:
                ;
                _RoleAni["jump_begin"].speed = 2f;
                _RoleAni["jump_down"].speed = 2f;
                _RoleAni.Play("jump_begin");
                _RoleAniState = RoleAniState.JUMP_BEGGIN;
                break;

            case RoleAniState.JUMP_DOWN:
                //_RoleAni.Play("111111111111111");
                break;

            case RoleAniState.JUMP_END:
                //_RoleAni.Play("111111111111111");
                break;

            case RoleAniState.DEATH:
                _RoleAni["death_sand"].speed = 1.5f;
                _RoleAni.Play("death_sand");
                _RoleAniState = RoleAniState.DEATH;
                _IsControll = false;
                if (!s_death.isPlaying)
                    s_death.Play();
                break;

            case RoleAniState.SACRIFICE:
                _RoleAni.Play("sacrifice");
                _RoleAniState = RoleAniState.SACRIFICE;
                _IsControll = false;
                break;

            case RoleAniState.WARSHOP:
                StartCoroutine(aaadsfdsdsf());
                _RoleAni.Play("warshop_normal");
                _RoleAniState = RoleAniState.WARSHOP;
                _IsControll = false;
                break;
        }

    }

    IEnumerator aaadsfdsdsf()
    {
        yield return new WaitForSeconds(3.3f);
        SetRoleAni(RoleAniState.STAND);
    }

    void OnTriggerEnter(Collider other)
    {
        switch (other.tag)
        {
            case "Ground"://接触到地面则死亡
               
                OnDeath();
                break;

            case "Prop"://收集到道具
                if (!s_eatCubeEffect.isPlaying)
                    s_eatCubeEffect.Play();
                if (!s_eatCube.isPlaying)
                    s_eatCube.Play();

                var go = (GameObject)Instantiate(Resources.Load("Prefab/Effects/CollectSouls"));
                go.transform.position = other.transform.position;
                Destroy(other.gameObject);
                StartCoroutine(waitDestroy1(go, 1f));
                break;

            case "BrokenBridge"://断桥
                other.gameObject.AddComponent<Rigidbody>();
                break;

            case "Altar"://祭拜祭坛
                AltarPos0 = GameLayoutInstance.GetInstance()._AltarObj.position;
                AltarPos1 = AltarPos0;

                isAltar = true;
                _IsControll = false;
                SetRoleAni(RoleAniState.WARSHOP);

                var sc = CameraController.GetInstance().gameObject.AddComponent<SwitchCamera>();
                if (!other.gameObject.name.Contains("doorTrigger"))
                {
                    if (!s_altarUP.isPlaying)
                        s_altarUP.Play();

                    AltarType = 0;
                    altatDis = 35f;
                    Destroy(other.gameObject);

                    GameLayoutInstance.GetInstance().SetBackGroundMusic2(); //祭坛起来后切换背景音乐
                    StartCoroutine(aaaa(1.1f));
                    sc.SetShakeCamera(4f, 1.5f, null);
                    
                }
                else
                {
                    if (!s_doorOpen.isPlaying)
                        s_doorOpen.Play();

                    altatDis = 20f;
                    AltarType = other.gameObject.name == "doorTrigger1" ? 1 : 2;
                    Destroy(other.gameObject);
                    StartCoroutine(aaaa(1.1f));
                    sc.SetShakeCamera(4f, 1.5f, null);
                }

                break;
        }
    }

    IEnumerator aaaa(float time)
    {
        yield return new WaitForSeconds(time);
        isMoveAltarObj = true;
    }

    void OnDeath()
    {
        if (isTriggerGround)
            return;
        isTriggerGround = true;

        CameraController.GetInstance()._isLookTarget = true;
        _IsControll = false;
        SetRoleAni(RoleAniState.DEATH);
        StartCoroutine(waitDestroy(this.gameObject, 1f));
    }

    /// <summary>
    /// 等待销毁(人物死亡触发后继续让他下落一段时间)
    /// </summary>
    /// <param name="go"></param>
    /// <param name="time"></param>
    /// <returns></returns>
    IEnumerator waitDestroy(GameObject go, float time)
    {
        yield return new WaitForSeconds(time);

        if (_OnDeathCallback != null)
            _OnDeathCallback(this);

        Destroy(go.gameObject);
        Destroy(_SoulBox);
        Destroy(_SoulBoxEffect);
    }

    IEnumerator waitDestroy1(GameObject go, float time)
    {
        yield return new WaitForSeconds(time);
        Destroy(go.gameObject);
    }

    void OnTriggerExit(Collider other)
    {

    }
}