using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;

public class Gun : MonoBehaviour
{

    [SerializeField] GunData gunData;
    [SerializeField] Transform Camera;
    
    public Animator animator;

    bool goUp = true;
    public AudioSource audioSource;
    public AudioClip shot;

    [SerializeField] PlayerLook pl;
    int shotsFired;
    float timeLastShot;
    float timeSinceLastGoUp;
    float recoilTemp;
    float upRecoilOffsetX;

    float overallRecoilOffsetX;
    float overallRecoilOffsetY;

    public GameObject decal;

    float timeSinceLastShot;
    private bool canShoot() => !gunData.reloading && timeSinceLastShot > 1f / (gunData.fireRate / 60f);

    private void Awake()
    {
        pl = transform.parent.transform.parent.GetComponent<PlayerLook>();
        Camera = transform.parent.transform.parent;
    }

    private void Start()
    {
        gunData.reloading = false;
        PlayerShoot.shootInput += Shoot;
        PlayerShoot.reloadInput += StartReload;
        PlayerShoot.recoilReset += RecoilReset;
    }   

    private void Update()
    {
        timeSinceLastShot += Time.deltaTime;
        timeLastShot += Time.deltaTime;
        if (!goUp)
        {
            timeSinceLastGoUp = 0f;
        }
        else
        {
            timeSinceLastGoUp += Time.deltaTime;
        }
        Debug.Log(timeSinceLastGoUp);
    }

    public void StartReload()
    {
        if(!gunData.reloading)
        {
            StartCoroutine(Reload());
        }
    }

    private IEnumerator Reload()
    {
        animator.Play("Reload");
        gunData.reloading = true;
        yield return new WaitForSeconds(gunData.reloadTime);

        gunData.currentAmmo = gunData.magSize;

        gunData.reloading = false;
        animator.Play("Idle");
    }

    public void Shoot()
    {
        if(gunData.currentAmmo > 0) 
        {
            if (canShoot())
            {
                if(goUp)
                {
                    if (timeLastShot >= gunData.recoilRecoveryTime && timeSinceLastGoUp >= gunData.recoilRecoveryTimeAfterUp)
                    {
                        shotsFired = 1;
                        //Debug.Log("reset shotsfired");
                    }
                    else
                    {
                        //Debug.Log("reoil set to old");
                        pl.recoil = recoilTemp;
                    }
                }
              
                //Add Recoil (1/Schuss)
                if (pl.recoil <= gunData.recoilHeight && goUp)
                {
                    pl.recoil += gunData.recoilPower / 1 * shotsFired;
                    recoilTemp = pl.recoil;
                    goUp = true;
                }
                else
                {
                    goUp = false;
                    pl.recoil = 0;
                }
                if(!goUp)
                {
                    RecoilPhaseTwo();
                }
                else if(shotsFired == 11)
                {
                    pl.recoilX = 0f;
                }

                if (shotsFired > 3 && shotsFired < 11)
                {
                    pl.recoilX += UnityEngine.Random.Range(gunData.upRecoilOffsetLimitX - upRecoilOffsetX, -gunData.upRecoilOffsetLimitX - upRecoilOffsetX);
                    upRecoilOffsetX += pl.recoilX;
                    Debug.Log("pl.recoilX = " + pl.recoilX);
                }

                if (shotsFired < 30)
                {
                    shotsFired++;
                }
                audioSource.PlayOneShot(shot);
                if (Physics.Raycast(Camera.transform.position, Camera.transform.forward, out RaycastHit hitinfo, gunData.maxDistance))
                {
                    IDamagable damageable = hitinfo.transform.GetComponent<IDamagable>();
                    damageable?.Damage(gunData.damage);

                    if (hitinfo.transform.gameObject.layer != 8 && hitinfo.transform.gameObject.layer != 7)
                    {
                        GameObject obj = Instantiate(decal, hitinfo.point, Quaternion.identity, hitinfo.transform);
                        obj.transform.rotation = Quaternion.LookRotation(hitinfo.normal);
                    }
                }

                gunData.currentAmmo--;
                timeSinceLastShot = 0;
                //Debug.Log("before reset" + timeLastShot);
                timeLastShot = 0;
                //Debug.Log("after reset" + timeLastShot);
            }
        }
        else
        {
            pl.recoil = 0;
            pl.recoilX = 0;
        }
    }

    //Recoilreset()
    void RecoilReset()
    {
        pl.recoil = 0;
        pl.recoilX = 0;
        goUp = true;
    }

    void RecoilPhaseTwo()
    {
        pl.recoilX = UnityEngine.Random.Range(gunData.overallRecoilOffsetLimitX - overallRecoilOffsetX, -gunData.overallRecoilOffsetLimitX - overallRecoilOffsetX);
        pl.recoil = UnityEngine.Random.Range(gunData.overallRecoilOffsetLimitY - overallRecoilOffsetY, -gunData.overallRecoilOffsetLimitY - overallRecoilOffsetY);

        overallRecoilOffsetX += pl.recoilX;
        overallRecoilOffsetY += pl.recoil;
    }

    private void OnDisable()
    {
        PlayerShoot.shootInput -= Shoot;
        PlayerShoot.reloadInput -= StartReload;
        PlayerShoot.recoilReset -= RecoilReset;
    }

}