using UdonSharp;
using UnityEngine;
using VRC.SDK3.Data;

namespace Marro.PacManUdon
{
    [RequireComponent(typeof(Animator))]
    [RequireComponent(typeof(Renderer))]
    public class BonusFruit : SyncedObject
    {
        private PacManFruitType fruitType;

        private Animator animator;
        private new Renderer renderer;
        private ScoreBonusDisplay scoreBonusDisplay;

        private bool active;
        private float activeCountdown;

        private int value;
        private bool frozen;

        public void Initialize()
        {
            animator = GetComponent<Animator>();
            renderer = GetComponent<Renderer>();
            scoreBonusDisplay = transform.Find("ScoreBonusDisplay").gameObject.GetComponent<ScoreBonusDisplay>();
            scoreBonusDisplay.Initialize();
            SetActive(false);
        }

        public override void SyncedUpdate()
        {
            if (!active || frozen)
            {
                return;
            }

            activeCountdown -= networkManager.SyncedDeltaTime;
            if (activeCountdown <= 0)
            {
                SetActive(false);
            }
        }

        public void Spawn()
        {
            // Debug.Log($"{gameObject} Spawned");
            SetActive(true);
            activeCountdown = Random.Range(9, 10);
        }

        public void Despawn()
        {
            // Debug.Log($"{gameObject} Despawned");
            SetActive(false);
        }

        public int Collected()
        {
            SetActive(false);
            scoreBonusDisplay.DisplayTemporarily(value, 1);
            return value;
        }

        public void SetFruitType(PacManFruitType fruitType)
        {
            value = (int)fruitScoreValue[PacManConstants.FruitTypeToValue(fruitType)];
            animator.SetFloat("FruitType", PacManConstants.FruitTypeToValue(fruitType));
        }

        public void SetFrozen(bool frozen)
        {
            this.frozen = frozen;
        }

        void SetActive(bool active)
        { // This replaces GameObject.active, as attempting to update an animator while a gameobject is inactive seems to result in a silent failure
            renderer.enabled = active;
            this.active = active;
        }

        public override void CollectSyncedData(byte[] data, ref int index, NetworkEventType eventType)
        {
            data.Append(active, ref index);

            if (!active)
            {
                return;
            }

            data.Append(activeCountdown, ref index);
            data.Append(frozen, ref index);
        }

        public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType)
        {
            SetActive(data.ReadBool(ref index));

            if (!active)
            {
                return true;
            }

            activeCountdown = data.ReadFloat(ref index);
            frozen = data.ReadBool(ref index);

            return true;
        }

        public bool Active => active;

        private readonly DataDictionary fruitScoreValue = new DataDictionary()
        {
            {(int)PacManFruitType.None      ,    0},
            {(int)PacManFruitType.Cherries  ,  100},
            {(int)PacManFruitType.Strawberry,  300},
            {(int)PacManFruitType.Peach     ,  500},
            {(int)PacManFruitType.Apple     ,  700},
            {(int)PacManFruitType.Grapes    , 1000},
            {(int)PacManFruitType.Galaxian  , 2000},
            {(int)PacManFruitType.Bell      , 3000},
            {(int)PacManFruitType.Key       , 5000}
        };
    }
}