﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

namespace Arugula.Games
{
    public class ScoreboardLabel : MonoBehaviour
    {
        public enum Type
        {
            Archived,
            Active
        }

        public enum Selector
        {
            Name,
            Index,
            First,
            Last,
            Meta
        }

        public TMP_Text textMesh;
        public string openingTag = null;
        public string closingTag = null;

        public string scoreboardName = "Points";
        public Type type;
        public Selector selector;
        public string id;
        public bool autoUpdate = true;
        public int padWidth = 8;
        public char padChar = '0';
        [Min(0)]
        public float damper = 0;
        public bool initialSnap = false;

        public SpriteRenderer iconRenderer;
        public Image iconImage;

        float goalValue;
        float smoothValue;

        Scoreboard sb;
        Scoreboard.Entry entry;

        public Scoreboard.Entry Entry
        {
            get => entry;
        }

        private IEnumerator Start()
        {
            sb = Scoreboard.Get(scoreboardName);

            if (iconRenderer)
                iconRenderer.sprite = sb.icon;
            if (iconImage)
                iconImage.sprite = sb.icon;

            Scoreboard.Entry e = null;

            Scoreboard.Collection c = null;

            switch (type)
            {
                case Type.Active:
                    c = sb.Active;
                    break;
                case Type.Archived:
                    c = sb.Archived;
                    break;
            }

            while (e == null)
            {
                switch (selector)
                {
                    case Selector.First:
                        e = c.First;
                        break;
                    case Selector.Last:
                        e = c.Last;
                        break;
                    case Selector.Index:
                        e = c[int.Parse(id)];
                        break;
                    case Selector.Name:
                        e = c[id];
                        break;
                    case Selector.Meta:
                        e = c.entries.FirstOrDefault(x => x.meta == id);
                        break;
                }

                if (e == null)
                    yield return null;
            }


            if (autoUpdate)
            {
                e.OnUpdated += EntryUpdated;
            }

            entry = e;
            if (initialSnap)
                smoothValue = goalValue = e.DisplayValue;
            else
                goalValue = e.DisplayValue;

            UpdateTextMeshes(smoothValue);
        }

        private void OnDestroy()
        {
            if (entry != null)
                entry.OnUpdated -= EntryUpdated;
        }

        private void EntryUpdated(Scoreboard.Entry e)
        {
            if (damper == 0)
            {
                goalValue = smoothValue = e.DisplayValue;
                UpdateTextMeshes(goalValue);
            }
            else
            {
                goalValue = e.DisplayValue;
            }
        }

        void UpdateTextMeshes(float value)
        {
            string str = (Mathf.RoundToInt(value)).ToString().PadLeft(padWidth, padChar);
            if (textMesh)
            {
                textMesh.text = $"{openingTag}{str}{closingTag}";
            }
        }

        private void Update()
        {
            if (entry == null || damper == 0)
                return;

            float prevVal = smoothValue;
            smoothValue = Mathf.SmoothStep(smoothValue, goalValue, Time.unscaledDeltaTime * damper);
            if (prevVal != smoothValue)
                UpdateTextMeshes(smoothValue);
        }
    }
}