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

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

        Animator animator;
        new Renderer renderer;
        new Collider collider;
        ScoreBonusDisplay scoreBonusDisplay;

        [UdonSynced] bool active;
        private int value;
        private float activeCountdown;
        private bool frozen;

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

        public override void SyncedUpdate()
        {
            if (active && !frozen)
            {
                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)
        {
            this.fruitType = 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;
            collider.enabled = active;
            this.active = active;
        }

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

        }

        public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType)
        {
            return true;
        }

        public PacManFruitType FruitType
        {
            set
            {
                SetFruitType(value);
            }
            get => fruitType;
        }

        public bool Active
        {
            set
            {
                SetActive(value);
            }
            get => 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}
        };
    }
}