﻿using System;
using System.Collections.Generic;
using JLGames.RocketDriver.Actions.ExcelExporter;
using JLGames.RocketDriver.CSharp.Service;
using JLGames.RocketDriver.Games.RpgMaterial.Common;
using JLGames.RocketDriver.Games.RpgMaterial.Material;
using JLGames.RocketDriver.Games.RpgMaterial.Service;
using JLGames.RocketDriver.Games.RpgMaterial.User;

namespace JLGames.RocketDriver.Samples.ServiceDemo.Service.Material
{
    public abstract class GameMaterialServiceBase<TU, TM, TCfg> : ServiceBase, IGameMaterialServiceMod, IMaterialServiceMod<TU, TM, TCfg>
        where TU : class, IUserMaterial<TM, TCfg>
        where TM : IMaterial<TCfg>, IInitMaterial<TCfg>
    {
        protected int m_Type;
        protected bool m_Unique;
        protected MaterialSet<TM, TCfg> m_Materials;
        protected UserMaterialSet<TU, TM, TCfg> m_UserMaterials;

        public int MaterialType => m_Type;
        public bool IsUnique => m_Unique;

        public GameMaterialServiceBase(int type, bool unique)
        {
            m_Type = type;
            m_Unique = unique;
        }

        public virtual void InitService()
        {
            m_Materials = new MaterialSet<TM, TCfg>();
            m_UserMaterials = new UserMaterialSet<TU, TM, TCfg>();
        }

        protected void InitMaterialData<TMImpl>(string fileName) where TMImpl : TM, new()
        {
            var text = ServiceCenter.ConfigDataService.ExtractJsonContext(fileName);

            var cfg = DataParsingUtil.ParseConfig<TCfg>(text);
            var set = new ElementSet<TM>();
            for (var i = 0; i < cfg.count; i++)
            {
                var impl = new TMImpl();
                impl.InitMaterial(cfg.data[i]);
                set.Add(impl);
            }

            m_Materials = new MaterialSet<TM, TCfg>(set);
        }

        protected void InitUserMaterialData()
        {
            m_UserMaterials = new UserMaterialSet<TU, TM, TCfg>();
        }

        public IGameMaterial GetGameMaterial(int mid)
        {
            return m_Materials.GetMaterial(mid) as IGameMaterial;
        }


        // IGameMaterialServiceMod

        public bool UpdateUserMaterial(UserNotifyData no)
        {
//            DebugUtil.Log("Base.UpdateUserMaterial:", no);
            var result = GameMaterialSetUtils.UpdateToSet(m_UserMaterials, no);
            if (!result.Succ) return false;
            NotifyMaterialUpdate(result);
            return true;
        }

        public int UpdateUserMaterials(UserNotifyData[] nos)
        {
//            DebugUtil.Log("Base.UpdateUserMaterials:", nos);
            var resuts = GameMaterialSetUtils.UpdateToSet(m_UserMaterials, nos);
            if (null == resuts || resuts.Length == 0) return 0;
            var rs = 0;
            foreach (var result in resuts)
            {
                if (!result.Succ) continue;
                NotifyMaterialUpdate(result);
                rs += 1;
            }

            DispatchEvent(GameMaterialEvents.OnNotifyMultiMaterialUpdate, nos);
            return rs;
        }

        public void UpdateUserMaterial(IGameUserMaterial um)
        {
            DispatchEvent(GameMaterialEvents.OnNotifyMaterialInstanceUpdate, um);
        }

        public void UpdateUserMaterials(IGameUserMaterial[] ums)
        {
            if (null == ums || ums.Length == 0) return;
            foreach (var um in ums)
            {
                DispatchEvent(GameMaterialEvents.OnNotifyMaterialInstanceUpdate, um);
            }

            DispatchEvent(GameMaterialEvents.OnNotifyMultiMaterialInstanceUpdate, ums);
        }

        protected void NotifyMaterialUpdate(MaterialUpdatedResult notify)
        {
//            DebugUtil.Log("Base.NotifyMaterialUpdate:", notify);
            DispatchEvent(GameMaterialEvents.OnNotifyMaterialUpdate, notify);
            if (notify.IsIncrease)
            {
                DispatchEvent(GameMaterialEvents.OnNotifyMaterialIncrease, notify);
                if (notify.IsNew) DispatchEvent(GameMaterialEvents.OnNotifyMaterialNew, notify);
                return;
            }

            if (notify.IsDecrease)
            {
                DispatchEvent(GameMaterialEvents.OnNotifyMaterialDecrease, notify);
                if (notify.IsDel) DispatchEvent(GameMaterialEvents.OnNotifyMaterialDel, notify);
                return;
            }
        }

        // Detegate 配置数据

        public int MaterialSize => m_Materials.MaterialSize;

        public bool ExistMaterial(int mId)
        {
            return m_Materials.ExistMaterial(mId);
        }

        public int GetSizeAs<TMAs>(Predicate<TMAs> match) where TMAs : class, IMaterial
        {
            return m_Materials.GetSizeAs(match);
        }

        public TMAs GetMaterialAs<TMAs>(int mId) where TMAs : class, IMaterial
        {
            return m_Materials.GetMaterialAs<TMAs>(mId);
        }

        public void ForeachMaterialAs<TMAs>(Action<TMAs> each) where TMAs : class, IMaterial
        {
            m_Materials.ForeachMaterialAs(each);
        }

        public int GetSize(Predicate<TM> match)
        {
            return m_Materials.GetSize(match);
        }

        public TM GetMaterial(int mId)
        {
            return m_Materials.GetMaterial(mId);
        }

        public TM[] GetMaterials()
        {
            return m_Materials.GetMaterials();
        }

        public TM[] GetMaterials(Predicate<TM> match)
        {
            return m_Materials.GetMaterials(match);
        }

        public void ForeachMaterial(Action<TM> each)
        {
            m_Materials.ForeachMaterial(each);
        }

        // Detegate 用户数据

        public int UserMaterialSize => m_UserMaterials.UserMaterialSize;

        public bool ExistUserMaterial(string eKey)
        {
            return m_UserMaterials.ExistUserMaterial(eKey);
        }

        public bool ExistUserMaterial(int mId)
        {
            return m_UserMaterials.ExistUserMaterial(mId);
        }

        public bool ExistUserMaterial(int mId, int uId)
        {
            return m_UserMaterials.ExistUserMaterial(mId, uId);
        }

        public int GetUserMaterialNum(string eKey)
        {
            return m_UserMaterials.GetUserMaterialNum(eKey);
        }

        public int GetUserMaterialNum(int mId)
        {
            return m_UserMaterials.GetUserMaterialNum(mId);
        }

        public int GetUserMaterialNum(int mId, int uId)
        {
            return m_UserMaterials.GetUserMaterialNum(mId, uId);
        }

        public TUAs GetUserMaterialAs<TUAs>(string eKey) where TUAs : IUserMaterial
        {
            return m_UserMaterials.GetUserMaterialAs<TUAs>(eKey);
        }

        public TUAs GetUserMaterialAs<TUAs>(int mId, int uId = 0) where TUAs : IUserMaterial
        {
            return m_UserMaterials.GetUserMaterialAs<TUAs>(mId, uId);
        }

        public TUAs[] GetUserMaterialsAs<TUAs>() where TUAs : IUserMaterial
        {
            return m_UserMaterials.GetUserMaterialsAs<TUAs>();
        }

        public TUAs[] GetUserMaterialsAs<TUAs>(int mId) where TUAs : IUserMaterial
        {
            return m_UserMaterials.GetUserMaterialsAs<TUAs>(mId);
        }

        public void ForeachUserMaterialAs<TUAs>(Action<TUAs> each) where TUAs : IUserMaterial
        {
            m_UserMaterials.ForeachUserMaterialAs(each);
        }

        public TUMod GetUserMaterialMod<TUMod>(string eKey) where TUMod : class, IUserMaterial, IUserMaterialMod
        {
            return m_UserMaterials.GetUserMaterialMod<TUMod>(eKey);
        }

        public TUMod GetUserMaterialMod<TUMod>(int mId, int uId = 0) where TUMod : class, IUserMaterial, IUserMaterialMod
        {
            return m_UserMaterials.GetUserMaterialMod<TUMod>(mId, uId);
        }

        public TUMod RemoveUserMaterialAs<TUMod>(string eKey) where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialAs<TUMod>(eKey);
        }

        public TUMod RemoveUserMaterialAs<TUMod>(int mId, int uId = 0) where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialAs<TUMod>(mId, uId);
        }

        public TUMod[] RemoveUserMaterialsAs<TUMod>(string[] eKeyArr) where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialsAs<TUMod>(eKeyArr);
        }

        public TUMod[] RemoveUserMaterialsAs<TUMod>(IEnumerable<string> eKeyArr) where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialsAs<TUMod>(eKeyArr);
        }

        public TUMod[] RemoveUserMaterialsAs<TUMod>(Predicate<TUMod> match) where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialsAs(match);
        }

        public TUMod[] RemoveUserMaterialsAs<TUMod>() where TUMod : class, IUserMaterial
        {
            return m_UserMaterials.RemoveUserMaterialsAs<TUMod>();
        }

        public void AddUserMaterialAs(IUserMaterial um)
        {
            m_UserMaterials.AddUserMaterialAs(um);
        }

        public void AddUserMaterialsAs<TUAs>(TUAs[] umArr) where TUAs : class, IUserMaterial
        {
            m_UserMaterials.AddUserMaterialsAs(umArr);
        }

        public void AddUserMaterialsAs<TUAs>(IEnumerable<TUAs> umArr) where TUAs : class, IUserMaterial
        {
            m_UserMaterials.AddUserMaterialsAs(umArr);
        }

        public void ReplaceUserMaterialAs(IUserMaterial um)
        {
            m_UserMaterials.ReplaceUserMaterialAs(um);
        }

        public void ReplaceUserMaterialsAs<TUAs>(TUAs[] umArr) where TUAs : class, IUserMaterial
        {
            m_UserMaterials.ReplaceUserMaterialsAs(umArr);
        }

        public void ReplaceUserMaterialsAs<TUAs>(IEnumerable<TUAs> umArr) where TUAs : class, IUserMaterial
        {
            m_UserMaterials.ReplaceUserMaterialsAs(umArr);
        }

        public int GetSize(Predicate<TU> match)
        {
            return m_UserMaterials.GetSize(match);
        }

        public TU GetUserMaterial(string eKey)
        {
            return m_UserMaterials.GetUserMaterial(eKey);
        }

        public TU GetUserMaterial(int mId, int uId = 0)
        {
            return m_UserMaterials.GetUserMaterial(mId, uId);
        }

        public TU[] GetUserMaterials()
        {
            return m_UserMaterials.GetUserMaterials();
        }

        public TU[] GetUserMaterials(int mId)
        {
            return m_UserMaterials.GetUserMaterials(mId);
        }

        public TU[] GetUserMaterials(Predicate<TU> match)
        {
            return m_UserMaterials.GetUserMaterials(match);
        }

        public void ForeachUserMaterial(Action<TU> each)
        {
            m_UserMaterials.ForeachUserMaterial(each);
        }

        public TU RemoveUserMaterial(string eKey)
        {
            return m_UserMaterials.RemoveUserMaterial(eKey);
        }

        public TU[] RemoveUserMaterials(string[] eKeyArr)
        {
            return m_UserMaterials.RemoveUserMaterials(eKeyArr);
        }

        public TU[] RemoveUserMaterials(IEnumerable<string> eKeyArr)
        {
            return m_UserMaterials.RemoveUserMaterials(eKeyArr);
        }

        public TU[] RemoveUserMaterials(Predicate<TU> match)
        {
            return m_UserMaterials.RemoveUserMaterials(match);
        }

        public TU[] RemoveUserMaterials()
        {
            return m_UserMaterials.RemoveUserMaterials();
        }

        public void AddUserMaterial(TU um)
        {
            m_UserMaterials.AddUserMaterial(um);
        }

        public void AddUserMaterials(TU[] umArr)
        {
            m_UserMaterials.AddUserMaterials(umArr);
        }

        public void AddUserMaterials(IEnumerable<TU> umArr)
        {
            m_UserMaterials.AddUserMaterials(umArr);
        }

        public void ReplaceUserMaterial(TU um)
        {
            m_UserMaterials.ReplaceUserMaterial(um);
        }

        public void ReplaceUserMaterials(TU[] umArr)
        {
            m_UserMaterials.ReplaceUserMaterials(umArr);
        }

        public void ReplaceUserMaterials(IEnumerable<TU> umArr)
        {
            m_UserMaterials.ReplaceUserMaterials(umArr);
        }
    }
}