using System;
using System.Collections.Generic;
using JNGame.Sync.Entity;
using JNGame.Sync.Frame.Entity;
using JNGame.Sync.System;
using UnityEngine;

namespace JNGame.Sync.View
{
    public class ViewGameObject
    {
        //更新
        public int Update;
        public GameObject Data;
    }
    
    public abstract class ViewData<T> : IViewData where T : ISData
    {
        
        private Dictionary<long, ViewGameObject> views = new();
        private SViewSystem root;
        public SViewSystem Root => root;

        private int Update = 0;
            
        public ViewData(SViewSystem root)
        {
            this.root = root;
        }

        public virtual void Execute()
        {
            Update++;
            
            var dataList = GetData();

            bool isRest = dataList.Length != views.Count;
            
            foreach (var data in dataList){
                
                ViewGameObject view;
                if (!views.TryGetValue(data.Id,out view))
                {
                    isRest = true;
                    view = new(){Data = NewView(data)};
                    views.Add(data.Id, view);
                }

                view.Update = Update;
                ViewUpdate(data,view.Data);
                
            }

            if (isRest)
            {
                List<long> deletes = new List<long>();
                foreach (var child in views)
                {
                    if (child.Value.Update != Update)
                    {
                        deletes.Add(child.Key);
                    }
                }
                foreach (var delete in deletes)
                {
                    ViewRemove(views[delete].Data);
                    views.Remove(delete);
                }
            }
            
        }
        public abstract void ViewUpdate(T data,GameObject view);
        public abstract GameObject NewView(T data);
        public abstract T[] GetData();

        public abstract void ViewRemove(GameObject view);
        
        public T GetService<T>() where T : SBaseSystem
        {
            return root.GetSystem<T>();
        }
        
    }
}