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

namespace JLGames.RocketDriver.Games.RpgMaterial.Service
{
    public abstract class MaterialService<TU, TM, TCfg> : ServiceBase,
        IMaterialService<TU, TM, TCfg>, IMaterialServiceMod<TU, TM, TCfg>,
        IUserMaterialGenerator<TU>, ITriggerRegister
        where TU : class, IUserMaterial<TM, TCfg>
        where TM : IMaterial<TCfg>
    {
        protected readonly int m_Type;
        protected readonly bool m_Unique;
        protected MaterialSet<TM, TCfg> m_Materials;
        protected UserMaterialSet<TU, TM, TCfg> m_UserMaterials;
        protected readonly MaterialServiceProxy<TU, TM, TCfg> m_Proxy;

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

        public MaterialService(int type, bool unique)
        {
            m_Type = type;
            m_Unique = unique;
            m_Proxy = new MaterialServiceProxy<TU, TM, TCfg>(type);
        }

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

        public override void Clear()
        {
            m_Proxy.ResetProxy();
            base.Clear();
        }

        // IUserMaterialGenerator

        public abstract IUserMaterial GenUserMaterial(int mid, int num = 0);

        public TU GenUserMaterialAs(int mid, int num = 0)
        {
            return GenUserMaterial(mid, num) as TU;
        }

        // ITriggerRegister

        public void RegisterTrigger(ITriggerEntity trigger)
        {
            m_Proxy.RegisterTrigger(trigger);
        }

        public int RegisterTrigger(Trigger.TrackingType tType, int mType, int eId, Trigger.CompareType cType, int cValue,
            Trigger.TriggerInvoke invokeFunc, bool post = true, int times = -1)
        {
            return m_Proxy.RegisterTrigger(tType, mType, eId, cType, cValue, invokeFunc, post, times);
        }

        public int RegisterOffsetTrigger(int mType, int eId, Trigger.CompareType cType, int cValue, Trigger.TriggerInvoke invokeFunc
            , bool post = true, int times = -1)
        {
            return m_Proxy.RegisterOffsetTrigger(mType, eId, cType, cValue, invokeFunc, post, times);
        }

        public int RegisterValueTrigger(int mType, int eId, Trigger.CompareType cType, int cValue, Trigger.TriggerInvoke invokeFunc
            , bool post = true, int times = -1)
        {
            return m_Proxy.RegisterOffsetTrigger(mType, eId, cType, cValue, invokeFunc, post, times);
        }

        public void UnregisterTrigger(ITriggerEntity trigger)
        {
            m_Proxy.UnregisterTrigger(trigger);
        }

        public void UnregisterTrigger(int triggerId)
        {
            m_Proxy.UnregisterTrigger(triggerId);
        }

        // IMaterialService<TU, TM, TCfg>: IMaterialSet

        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);
        }

        // IMaterialService<TU, TM, TCfg>: IMaterialSet<TM, TCfg>

        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);
        }

        // IMaterialService<TU, TM, TCfg>: IUserMaterialSet

        public int UserMaterialSize => m_UserMaterials.UserMaterialSize;

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

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

        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);
        }

        // IMaterialService<TU, TM, TCfg>: IUserMaterialSet<TU, TM, TCfg>

        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);
        }

        // IMaterialServiceMod<TU, TM, TCfg> : IUserMaterialSetMod

        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);
        }

        // IMaterialServiceMod<TU, TM, TCfg> : IUserMaterialSetMod<TU, TM, TCfg>

        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);
        }
    }
}