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

public class FFishSystem : MonoBehaviour
{
    [Serializable]
    public class FeedingZoneGroup
    {
        public enum FishMoveType
        {
            None = 0,
            Random = 1,
            Loop = 2,
            OneWay = 3
        }

        public List<FishFeedingZone> fishFeedingZones;

        public FishMoveType fishMoveType;

        public bool isRandom;

        public bool isLoop;

        public bool isNoRepeat;

        public Color connectLineGizmos = Color.red;
    }

    public bool isNewSpawnerSystem = true;

    public List<FWaterDisplacement> inwaterObjects;

    public List<FWaterDisplacement> baitsObjects;

    public List<FFish> inwaterFishObjects;

    public List<FFish> inwaterFishObjectsSpawner;

    public List<FeedingZoneGroup> feedingZoneGroup;

    public bool viewDebugFish = true;

    public int maxVievFishAmount = 15;

    public int currentFishViewAmount;

    [SerializeField] private int fishToSpawnAmount;


    [SerializeField] public bool isReadySetup;

    private int maximumFishPoints = 20;

    private float timerToReady;

    private void Start()
    {
        isReadySetup = false;
        if (!isNewSpawnerSystem)
        {
            SetupFeedingZones();
        }
        else
        {
            InvokeRepeating("ReSpawnerSystem", 1f, 1f);
        }

        inwaterFishObjectsSpawner = new List<FFish>();
        InvokeRepeating("RefreshCurrentFishView", 30f, 30f);
    }

    private void Update()
    {
        if (!isNewSpawnerSystem)
        {
            if (!isReadySetup && fishToSpawnAmount == inwaterFishObjects.Count)
            {
                if (!isReadySetup)
                {
                    Debug.Log("Zakończono spawnowania ryb: " + inwaterFishObjects.Count);
                }

                isReadySetup = true;
                InvokeRepeating("RefreshFishOptimize", 2f, 2f);
            }
        }
        else if (!isReadySetup)
        {
            isReadySetup = true;
        }
    }

    private void FixedUpdate()
    {
        if (isReadySetup)
        {
            if (!isNewSpawnerSystem)
            {
                FishDisabledMovement();
            }
        }
    }

    private void ReSpawnerSystem()
    {
        // if (eagleEyes.isFishView)
        // {
        //     return;
        // }

        baitsObjects.Clear();
        FWaterDisplacement[] array = FindObjectsOfType<FWaterDisplacement>();
        for (int i = 0; i < array.Length; i++)
        {
            if (array[i].CompareTag("BaitLure"))
            {
                baitsObjects.Add(array[i]);
            }
        }

        if (baitsObjects.Count > 0)
        {
            ReassignFishOrDestroyHookObject();
            fishToSpawnAmount = Mathf.RoundToInt(maximumFishPoints / baitsObjects.Count);
            DeleteFishOffRange();
            for (int j = 0; j < baitsObjects.Count; j++)
            {
                GenerateOnFish(baitsObjects[j].transform.position, baitsObjects[j]);
            }
        }
    }

    private void DeleteFishOffRange()
    {
        // for (int i = 0;
        //      i < inwaterFishObjectsSpawner.Count && (!(Vector3.Distance(inwaterFishObjectsSpawner[i].transform.position,
        //          FScriptsHandler.Instance.m_PlayerMain.currentCameraView
        //              .transform.position) < 15f));
        //      i++)
        // {
        //     for (int j = 0; j < baitsObjects.Count; j++)
        //     {
        //         if (baitsObjects[j].fishListCreated.Contains(inwaterFishObjectsSpawner[i]) &&
        //             Vector3.Distance(inwaterFishObjectsSpawner[i].transform.position,
        //                 baitsObjects[j].transform.position) > 30f &&
        //             inwaterFishObjectsSpawner[i].transform.position.y < 0f &&
        //             inwaterFishObjectsSpawner[i].joiner == null)
        //         {
        //             baitsObjects[j].fishListCreated.Remove(inwaterFishObjectsSpawner[i]);
        //             Destroy(inwaterFishObjectsSpawner[i].gameObject);
        //         }
        //     }
        // }
    }

    private void DeleteOneFishFromHookObject(FWaterDisplacement hookObject)
    {
        // for (int i = 0; i < hookObject.fishListCreated.Count; i++)
        // {
        //     if (Vector3.Distance(hookObject.fishListCreated[i].transform.position, hookObject.transform.position) >
        //         10f && hookObject.fishListCreated[i].joiner == null &&
        //         hookObject.fishListCreated[i].currentSearchBaitLure == null && !hookObject.fishListCreated[i].isGetFish)
        //     {
        //         if (!(Vector3.Distance(hookObject.fishListCreated[i].transform.position,
        //                 FScriptsHandler.Instance.m_PlayerMain.currentCameraView.transform.position) < 15f))
        //         {
        //             Destroy(hookObject.fishListCreated[i].gameObject);
        //         }
        //
        //         break;
        //     }
        // }
    }

    public void RemoveFishFromCurrentHook(FFish fish)
    {
        for (int i = 0; i < baitsObjects.Count; i++)
        {
            if (baitsObjects[i].fishListCreated.Contains(fish))
            {
                baitsObjects[i].fishListCreated.Remove(fish);
            }
        }
    }

    private void ReassignFishOrDestroyHookObject()
    {
        for (int i = 0; i < inwaterFishObjectsSpawner.Count; i++)
        {
            bool flag = false;
            for (int j = 0; j < baitsObjects.Count; j++)
            {
                if (baitsObjects[j].fishListCreated.Contains(inwaterFishObjectsSpawner[i]))
                {
                    flag = true;
                }
            }

            if (!flag)
            {
                baitsObjects[UnityEngine.Random.Range(0, baitsObjects.Count - 1)].fishListCreated
                    .Add(inwaterFishObjectsSpawner[i]);
            }
        }
    }

    private void GenerateOnFish(Vector3 currPosition, FWaterDisplacement hookObject = null)
    {
        if (feedingZoneGroup.Count == 0)
        {
            return;
        }

        if ((bool)hookObject)
        {
            if (fishToSpawnAmount < hookObject.fishListCreated.Count)
            {
                DeleteOneFishFromHookObject(hookObject);
                return;
            }

            if (fishToSpawnAmount == hookObject.fishListCreated.Count)
            {
                return;
            }
        }

        bool flag = false;
        Vector3 vector = currPosition + UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(20f, 25f);
        if (Vector3.Distance(vector, currPosition) < 15f)
        {
            return;
        }

        float num = ProbeDeepToTerenFromWater(vector);
        if (num < 0.3f || num == 0f)
        {
            return;
        }

        vector.y = UnityEngine.Random.Range(0f - num, 0f - num * 0.5f);
        for (int i = 0; i < feedingZoneGroup.Count; i++)
        {
            for (int j = 0; j < feedingZoneGroup[i].fishFeedingZones.Count; j++)
            {
                if (Vector3.Distance(currPosition, feedingZoneGroup[i].fishFeedingZones[j].transform.position) <
                    feedingZoneGroup[i].fishFeedingZones[j].rangeZone && ProbeDeepToTerenBottom(vector))
                {
                    StartCoroutine(feedingZoneGroup[i].fishFeedingZones[j].GenerateOneFish(vector, hookObject));
                    flag = true;
                    Debug.Log("Generate fish in zone");
                }
            }
        }

        if (!flag && ProbeDeepToTerenBottom(vector))
        {
            StartCoroutine(feedingZoneGroup[0].fishFeedingZones[0].GenerateOneFish(vector, hookObject));
            Debug.Log("Generate fish first zone");
        }
    }

    private void RefreshFishOptimize()
    {
        // if (!eagleEyes.isFishView)
        // {
        //     StartCoroutine(FishOptimize());
        // }
    }

    private void SetupFeedingZones()
    {
        for (int i = 0; i < feedingZoneGroup.Count; i++)
        {
            for (int j = 0; j < feedingZoneGroup[i].fishFeedingZones.Count; j++)
            {
                for (int k = 0; k < feedingZoneGroup[i].fishFeedingZones[j].fishPopulation.Length; k++)
                {
                    fishToSpawnAmount += feedingZoneGroup[i].fishFeedingZones[j].fishPopulation[k].AmountPopulationZone;
                }
            }
        }

        for (int l = 0; l < feedingZoneGroup.Count; l++)
        {
            for (int m = 0; m < feedingZoneGroup[l].fishFeedingZones.Count; m++)
            {
                feedingZoneGroup[l].fishFeedingZones[m].fFishSystem = this;
                feedingZoneGroup[l].fishFeedingZones[m].Inedex = m;
                feedingZoneGroup[l].fishFeedingZones[m].InedexOfGroup = l;
                StartCoroutine(feedingZoneGroup[l].fishFeedingZones[m].GenerateFishPopulationOnStart());
            }
        }
    }

    private void FishDisabledMovement()
    {
        for (int i = 0; i < feedingZoneGroup.Count; i++)
        {
            for (int j = 0; j < feedingZoneGroup[i].fishFeedingZones.Count; j++)
            {
                for (int k = 0; k < feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone.Count; k++)
                {
                    if (feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k] != null && !feedingZoneGroup[i]
                            .fishFeedingZones[j].fishesOnZone[k].gameObject.activeSelf)
                    {
                        Vector3 targetPoint = feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].TargetPoint;
                        feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].transform.position =
                            Vector3.MoveTowards(
                                feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].transform.position, targetPoint,
                                Time.deltaTime * 0.8f);
                        if (feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].transform.position == targetPoint)
                        {
                            feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone =
                                GetNewTargetFeedingZone(feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k]);
                            feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].TargetPoint =
                                feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone.transform
                                    .position + new Vector3(
                                    UnityEngine.Random.Range(
                                        0f - feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone
                                            .rangeZone,
                                        feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone
                                            .rangeZone), UnityEngine.Random.Range(-1f, -0.2f),
                                    UnityEngine.Random.Range(
                                        0f - feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone
                                            .rangeZone,
                                        feedingZoneGroup[i].fishFeedingZones[j].fishesOnZone[k].currentFeedingZone
                                            .rangeZone));
                        }
                    }
                }
            }
        }
    }

    public FishFeedingZone GetNewTargetFeedingZone(FFish currentFish)
    {
        int inedexOfGroup = currentFish.currentFeedingZone.InedexOfGroup;
        int inedex = currentFish.currentFeedingZone.Inedex;
        int count = feedingZoneGroup[inedexOfGroup].fishFeedingZones.Count;
        FishFeedingZone result = null;
        int num = 0;
        switch (feedingZoneGroup[inedexOfGroup].fishMoveType)
        {
            case FeedingZoneGroup.FishMoveType.None:
                if (currentFish.feedingZoneMoveState == 0)
                {
                    num = inedex + 1;
                    if (num >= count)
                    {
                        currentFish.feedingZoneMoveState = 1;
                        num = inedex - 1;
                    }
                }

                if (currentFish.feedingZoneMoveState == 1)
                {
                    num = inedex - 1;
                    if (num < 0)
                    {
                        currentFish.feedingZoneMoveState = 0;
                        num = inedex + 1;
                    }
                }

                result = feedingZoneGroup[inedexOfGroup].fishFeedingZones[num];
                break;
            case FeedingZoneGroup.FishMoveType.Loop:
                num = inedex + 1;
                if (num >= count)
                {
                    currentFish.feedingZoneMoveState = 0;
                    num = 0;
                }

                result = feedingZoneGroup[inedexOfGroup].fishFeedingZones[num];
                break;
            case FeedingZoneGroup.FishMoveType.Random:
                num = UnityEngine.Random.Range(0, count);
                result = feedingZoneGroup[inedexOfGroup].fishFeedingZones[num];
                break;
            case FeedingZoneGroup.FishMoveType.OneWay:
                num = inedex + 1;
                if (num >= count)
                {
                    currentFish.transform.position =
                        feedingZoneGroup[inedexOfGroup].fishFeedingZones[0].transform.position + new Vector3(
                            UnityEngine.Random.Range(0f - feedingZoneGroup[inedexOfGroup].fishFeedingZones[0].rangeZone,
                                feedingZoneGroup[inedexOfGroup].fishFeedingZones[0].rangeZone),
                            UnityEngine.Random.Range(-1f, -0.2f),
                            UnityEngine.Random.Range(0f - feedingZoneGroup[inedexOfGroup].fishFeedingZones[0].rangeZone,
                                feedingZoneGroup[inedexOfGroup].fishFeedingZones[0].rangeZone));
                    num = 1;
                }

                result = feedingZoneGroup[inedexOfGroup].fishFeedingZones[num];
                break;
        }

        return result;
    }

    private void OnDrawGizmos()
    {
        for (int i = 0; i < feedingZoneGroup.Count; i++)
        {
            switch (feedingZoneGroup[i].fishMoveType)
            {
                case FeedingZoneGroup.FishMoveType.None:
                {
                    for (int k = 0; k < feedingZoneGroup[i].fishFeedingZones.Count - 1; k++)
                    {
                        Gizmos.color = feedingZoneGroup[i].connectLineGizmos;
                        Gizmos.DrawLine(feedingZoneGroup[i].fishFeedingZones[k].transform.position,
                            feedingZoneGroup[i].fishFeedingZones[k + 1].transform.position);
                    }

                    break;
                }
                case FeedingZoneGroup.FishMoveType.Loop:
                {
                    for (int l = 0; l < feedingZoneGroup[i].fishFeedingZones.Count - 1; l++)
                    {
                        Gizmos.color = feedingZoneGroup[i].connectLineGizmos;
                        Gizmos.DrawLine(feedingZoneGroup[i].fishFeedingZones[l].transform.position,
                            feedingZoneGroup[i].fishFeedingZones[l + 1].transform.position);
                    }

                    Gizmos.DrawLine(
                        feedingZoneGroup[i].fishFeedingZones[feedingZoneGroup[i].fishFeedingZones.Count - 1].transform
                            .position, feedingZoneGroup[i].fishFeedingZones[0].transform.position);
                    break;
                }
                case FeedingZoneGroup.FishMoveType.Random:
                {
                    for (int m = 0; m < feedingZoneGroup[i].fishFeedingZones.Count; m++)
                    {
                        for (int n = 0; n < feedingZoneGroup[i].fishFeedingZones.Count; n++)
                        {
                            Gizmos.color = feedingZoneGroup[i].connectLineGizmos;
                            Gizmos.DrawLine(feedingZoneGroup[i].fishFeedingZones[m].transform.position,
                                feedingZoneGroup[i].fishFeedingZones[n].transform.position);
                        }
                    }

                    break;
                }
                case FeedingZoneGroup.FishMoveType.OneWay:
                {
                    for (int j = 0; j < feedingZoneGroup[i].fishFeedingZones.Count - 1; j++)
                    {
                        Gizmos.color = feedingZoneGroup[i].connectLineGizmos;
                        Gizmos.DrawLine(feedingZoneGroup[i].fishFeedingZones[j].transform.position,
                            feedingZoneGroup[i].fishFeedingZones[j + 1].transform.position);
                    }

                    Gizmos.color = Color.black;
                    Gizmos.DrawSphere(
                        feedingZoneGroup[i].fishFeedingZones[feedingZoneGroup[i].fishFeedingZones.Count - 1].transform
                            .position, 0.3f);
                    break;
                }
            }

            if (!viewDebugFish)
            {
                continue;
            }

            for (int num = 0; num < feedingZoneGroup[i].fishFeedingZones.Count; num++)
            {
                for (int num2 = 0; num2 < feedingZoneGroup[i].fishFeedingZones[num].fishesOnZone.Count; num2++)
                {
                    if (feedingZoneGroup[i].fishFeedingZones[num].fishesOnZone[num2] != null)
                    {
                        Gizmos.color = feedingZoneGroup[i].connectLineGizmos;
                        Gizmos.DrawSphere(
                            feedingZoneGroup[i].fishFeedingZones[num].fishesOnZone[num2].transform.position, 0.2f);
                    }
                }
            }
        }
    }

    private void RefreshCurrentFishView()
    {
        currentFishViewAmount = 0;
        for (int i = 0; i < inwaterFishObjects.Count; i++)
        {
            if (inwaterFishObjects[i].gameObject.activeSelf)
            {
                currentFishViewAmount++;
            }
        }

        Debug.Log("RefreshCurrentFishView: " + currentFishViewAmount);
    }

    private IEnumerator FishOptimize()
    {
        // for (int i = 0; i < inwaterFishObjects.Count; i++)
        // {
        //     if (!(inwaterFishObjects[i] != null) || (bool)inwaterFishObjects[i].currentSearchBaitLure ||
        //         (bool)inwaterFishObjects[i].currentBaitLure)
        //     {
        //         continue;
        //     }
        //
        //     float num = Vector3.Distance(FScriptsHandler.Instance.m_PlayerMain.currentCameraView.transform.position,
        //         inwaterFishObjects[i].transform.position);
        //     float num2 = 0f;
        //     bool flag = false;
        //     for (int j = 0; j < inwaterObjects.Count; j++)
        //     {
        //         if (inwaterObjects[j].tag == "BaitLure")
        //         {
        //             num2 = Vector3.Distance(inwaterObjects[j].transform.position,
        //                 inwaterFishObjects[i].transform.position);
        //             if (inwaterObjects[j].isInWater)
        //             {
        //                 flag = true;
        //             }
        //         }
        //     }
        //
        //     Vector3.Angle(
        //         inwaterFishObjects[i].transform.position -
        //         FScriptsHandler.Instance.m_PlayerMain.currentCameraView.transform.position,
        //         FScriptsHandler.Instance.m_PlayerMain.m_Camera.transform.forward);
        //     if (flag || num < 15f)
        //     {
        //         if (flag && num2 < 15f && num2 > 10f)
        //         {
        //             if (!inwaterFishObjects[i].gameObject.activeSelf && currentFishViewAmount < maxVievFishAmount &&
        //                 inwaterFishObjects[i].transform.position.y < -0.5f &&
        //                 ProbeDeepToTerenBottom(inwaterFishObjects[i].transform.position))
        //             {
        //                 inwaterFishObjects[i].EnableFish();
        //                 inwaterFishObjects[i].TimerToDisable = 5f;
        //                 currentFishViewAmount++;
        //                 yield return null;
        //             }
        //         }
        //         // else if (num < 15f && num > 10f && (bool)FScriptsHandler.Instance.playerManager.freeCamera && !inwaterFishObjects[i].gameObject.activeSelf && currentFishViewAmount < maxVievFishAmount && inwaterFishObjects[i].transform.position.y < -0.5f && ProbeDeepToTerenBottom(inwaterFishObjects[i].transform.position))
        //         else if (num < 15f && num > 10f &&
        //                  !inwaterFishObjects[i].gameObject.activeSelf && currentFishViewAmount < maxVievFishAmount &&
        //                  inwaterFishObjects[i].transform.position.y < -0.5f &&
        //                  ProbeDeepToTerenBottom(inwaterFishObjects[i].transform.position))
        //         {
        //             inwaterFishObjects[i].EnableFish();
        //             inwaterFishObjects[i].TimerToDisable = 5f;
        //             currentFishViewAmount++;
        //             yield return null;
        //         }
        //     }
        //     else if (inwaterFishObjects[i].gameObject.activeSelf && inwaterFishObjects[i].TimerToDisable == 0f &&
        //              currentFishViewAmount > 0)
        //     {
        //         inwaterFishObjects[i].gameObject.SetActive(value: false);
        //         currentFishViewAmount--;
        //     }
        // }
        yield break;
    }

    private bool ProbeDeepToTerenBottom(Vector3 probeObject)
    {
        int layerMask = LayerMask.GetMask("Terrain") | LayerMask.GetMask("UnderwaterObject");
        if (Physics.Raycast(probeObject, -Vector3.up, out var _, float.PositiveInfinity, layerMask))
        {
            return true;
        }

        return false;
    }

    private float ProbeDeepToTerenFromWater(Vector3 probeObject)
    {
        probeObject.y = 0f;
        int layerMask = LayerMask.GetMask("Terrain") | LayerMask.GetMask("UnderwaterObject");
        if (Physics.Raycast(probeObject, -Vector3.up, out var hitInfo, float.PositiveInfinity, layerMask))
        {
            return hitInfo.distance;
        }

        return 0f;
    }

    public void AddInwaterObject(FWaterDisplacement wIobj)
    {
        if (!inwaterObjects.Contains(wIobj))
        {
            inwaterObjects.Add(wIobj);
        }
    }

    public void DeleteInwaterObject(FWaterDisplacement wIobj)
    {
        if (inwaterObjects.Contains(wIobj))
        {
            inwaterObjects.Remove(wIobj);
        }
    }

    public void AddInwaterFishObject(FFish wIobj)
    {
        if (!inwaterFishObjects.Contains(wIobj))
        {
            inwaterFishObjects.Add(wIobj);
        }
    }

    public void DeleteInwaterFishObject(FFish wIobj)
    {
        if (inwaterFishObjects.Contains(wIobj))
        {
            inwaterFishObjects.Remove(wIobj);
        }

        RemoveFishFromCurrentHook(wIobj);
    }
}