using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using CommonLang;
using CommonLang.IO;
using CommonLang.IO.Attribute;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using CommonAI.Zone.Instance;
using CommonAI.Zone.Formula;
using CommonLang.Property;
using CommonLang.Log;
using CommonLang.Xml;
using CommonAI.Zone.Helper;
using CommonLang.Concurrent;
using System.Xml;
using CommonLang.Protocol;
using CommonAI.Zone.Simple;

namespace CommonAI.Zone
{
    public class TemplateManager
    {
        //----------------------------------------------------------------------------------------------
        #region _STATIC_

        private static bool s_IsEditor = false;
        private static InstanceZoneFactory s_Factory = new SimpleInstanceZoneFactory();
        private static MessageFactoryGenerator s_Codec = new MessageFactoryGenerator();
        public static bool IsEditor { get { return s_IsEditor; } set { s_IsEditor = value; } }
        public static IFormula Formula
        {
            get { return s_Factory.Formula; }
        }
        public static MessageFactoryGenerator MessageCodec { get { return s_Codec; } }
        public static InstanceZoneFactory Factory
        {
            get { return s_Factory; }
        }
        public static void setFactory(InstanceZoneFactory factory)
        {
            TemplateManager.s_Factory = factory;
            TemplateManager.s_Codec.RegistAssembly(AppDomain.CurrentDomain.GetAssemblies());
            ZoneEditor.EventTrigger.GameFields.InitFiledManager();
        }
        public static InstanceZoneFactory LoadFactory(string plugin)
        {
            Type type = ReflectionUtil.GetType(plugin);
            InstanceZoneFactory factory = (InstanceZoneFactory)ReflectionUtil.CreateInstance(type);
            TemplateManager.setFactory(factory);
            return factory;
        }

        #endregion

        //----------------------------------------------------------------------------------------------
        private Config mConfig;
        private ICommonConfig mExtConfig;
        private TerrainDefinitionMap mTerrainDefinition;
        private UnitActionDefinitionMap mUnitActionDefinition;
        private HashMap<UnitActionStatus, UnitActionDefinitionMap.UnitAction> mUnitActionMap = new HashMap<UnitActionStatus, UnitActionDefinitionMap.UnitAction>();

        private HashMap<int, UnitInfo> mUnits = new HashMap<int, UnitInfo>();
        private HashMap<int, SkillTemplate> mSkills = new HashMap<int, SkillTemplate>();
        private HashMap<int, SpellTemplate> mSpells = new HashMap<int, SpellTemplate>();
        private HashMap<int, BuffTemplate> mBuffs = new HashMap<int, BuffTemplate>();
        private HashMap<int, ItemTemplate> mItems = new HashMap<int, ItemTemplate>();
        private HashMap<int, UnitTriggerTemplate> mUnitTriggers = new HashMap<int, UnitTriggerTemplate>();
        private HashMap<int, UnitEventTemplate> mUnitEvents = new HashMap<int, UnitEventTemplate>();
        //----------------------------------------------------------------------------------------------

        public TemplateManager()
        {
            mConfig = new Config();
            this.mExtConfig = s_Factory.CreateCommonCFG();
            mTerrainDefinition = new TerrainDefinitionMap();
            mUnitActionDefinition = new UnitActionDefinitionMap();
        }

        public string ResourceVersion { get; internal set; }

        public Config CFG
        {
            get { return mConfig; }
            internal set { mConfig = value; }
        }
        public ICommonConfig ExtConfig
        {
            get { return mExtConfig; }
            internal set { mExtConfig = value; }
        }
        public TerrainDefinitionMap TerrainDefinition
        {
            get { return mTerrainDefinition; }
            internal set { mTerrainDefinition = value; }
        }
        public UnitActionDefinitionMap UnitActionDefinition
        {
            get { return mUnitActionDefinition; }
            internal set
            {
                mUnitActionDefinition = value;
                mUnitActionMap.Clear();
                foreach (var a in value.ActionMap)
                {
                    mUnitActionMap.Put(a.Action, a);
                }
            }
        }
        public UnitActionDefinitionMap.UnitAction GetDefinedUnitAction(UnitActionStatus act)
        {
            UnitActionDefinitionMap.UnitAction ret;
            mUnitActionMap.TryGetValue(act, out ret);
            return ret;
        }
        //----------------------------------------------------------------------------------------------

        //----------------------------------------------------------------------------------------------

        //----------------------------------------------------------------------------------------------
        #region UNITS

        public List<UnitInfo> getAllUnits()
        {
            return new List<UnitInfo>(mUnits.Values);
        }

		public HashMap<int, UnitInfo> getUnits()
		{
			return mUnits;
		}

		internal void addUnit(UnitInfo st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mUnits.Put(st.ID, st);
        }

        public UnitInfo getUnit(int id)
        {
            UnitInfo st;
            if (mUnits.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, UnitInfo> getUnits(List<int> units)
        {
            Dictionary<int, UnitInfo> ret = new Dictionary<int, UnitInfo>();
            foreach (int uid in units)
            {
                UnitInfo st = getUnit(uid);
                if (st != null && !ret.ContainsKey(uid))
                {
                    ret.Add(uid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region SKILLS

        public List<SkillTemplate> getAllSkills()
        {
            return new List<SkillTemplate>(mSkills.Values);
        }

		public HashMap<int, SkillTemplate> getAllSkillData()
		{
			return mSkills;
		}

		internal void addSkill(SkillTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mSkills.Put(st.ID, st);
        }

        public SkillTemplate getSkill(int id)
        {
            SkillTemplate st;
            if (mSkills.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, SkillTemplate> getSkills(List<int> skills)
        {
            Dictionary<int, SkillTemplate> ret = new Dictionary<int, SkillTemplate>();
            foreach (int skillID in skills)
            {
                SkillTemplate st = getSkill(skillID);
                if (st != null && !ret.ContainsKey(skillID))
                {
                    ret.Add(skillID, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region SPELLS

        public List<SpellTemplate> getAllSpells()
        {
            return new List<SpellTemplate>(mSpells.Values);
        }

        internal void addSpell(SpellTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mSpells.Put(st.ID, st);
        }

        public SpellTemplate getSpell(int id)
        {
            SpellTemplate st;
            if (mSpells.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, SpellTemplate> getSpells(List<int> spells)
        {
            Dictionary<int, SpellTemplate> ret = new Dictionary<int, SpellTemplate>();
            foreach (int sid in spells)
            {
                SpellTemplate st = getSpell(sid);
                if (st != null && !ret.ContainsKey(sid))
                {
                    ret.Add(sid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region BUFFS

        public List<BuffTemplate> getAllBuffs()
        {
            return new List<BuffTemplate>(mBuffs.Values);
        }

        internal void addBuff(BuffTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mBuffs.Put(st.ID, st);
        }

        public BuffTemplate getBuff(int id)
        {
            BuffTemplate st;
            if (mBuffs.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, BuffTemplate> getBuffs(List<int> spells)
        {
            Dictionary<int, BuffTemplate> ret = new Dictionary<int, BuffTemplate>();
            foreach (int sid in spells)
            {
                BuffTemplate st = getBuff(sid);
                if (st != null && !ret.ContainsKey(sid))
                {
                    ret.Add(sid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region ITEMS

        public List<ItemTemplate> getAllItems()
        {
            return new List<ItemTemplate>(mItems.Values);
        }

        internal void addItem(ItemTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mItems.Put(st.ID, st);
        }

        public ItemTemplate getItem(int id)
        {
            ItemTemplate st;
            if (mItems.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, ItemTemplate> getItems(List<int> items)
        {
            Dictionary<int, ItemTemplate> ret = new Dictionary<int, ItemTemplate>();
            foreach (int sid in items)
            {
                ItemTemplate st = getItem(sid);
                if (st != null && !ret.ContainsKey(sid))
                {
                    ret.Add(sid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region UNIT_TRIGGERS

        public List<UnitTriggerTemplate> getAllUnitTriggers()
        {
            return new List<UnitTriggerTemplate>(mUnitTriggers.Values);
        }

        internal void addUnitTrigger(UnitTriggerTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mUnitTriggers.Put(st.ID, st);
        }

        public UnitTriggerTemplate getUnitTrigger(int id)
        {
            UnitTriggerTemplate st;
            if (mUnitTriggers.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, UnitTriggerTemplate> getUnitTriggers(List<int> items)
        {
            Dictionary<int, UnitTriggerTemplate> ret = new Dictionary<int, UnitTriggerTemplate>();
            foreach (int sid in items)
            {
                UnitTriggerTemplate st = getUnitTrigger(sid);
                if (st != null && !ret.ContainsKey(sid))
                {
                    ret.Add(sid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------
        #region UNIT_EVENTS

        public List<UnitEventTemplate> getAllUnitEvents()
        {
            return new List<UnitEventTemplate>(mUnitEvents.Values);
        }

        internal void addUnitEvent(UnitEventTemplate st)
        {
            if (st.ID == 0)
            {
                throw new Exception("ID=0不是一个有效的ID:" + st);
            }
            mUnitEvents.Put(st.ID, st);
        }

        public UnitEventTemplate getUnitEvent(int id)
        {
            UnitEventTemplate st;
            if (mUnitEvents.TryGetValue(id, out st))
            {
                return st;
            }
            return null;
        }

        public Dictionary<int, UnitEventTemplate> getUnitEvents(List<int> items)
        {
            Dictionary<int, UnitEventTemplate> ret = new Dictionary<int, UnitEventTemplate>();
            foreach (int sid in items)
            {
                UnitEventTemplate st = getUnitEvent(sid);
                if (st != null && !ret.ContainsKey(sid))
                {
                    ret.Add(sid, st);
                }
            }
            return ret;
        }

        #endregion
        //----------------------------------------------------------------------------------------------

        private HashMap<Type, HashMap<uint, ISNData>> mSnDataMap = new HashMap<Type, HashMap<uint, ISNData>>();
        private HashMap<uint, ISNData> mCurrentSceneSnDataMap = new HashMap<uint, ISNData>();

        private int Rehash(object data)
        {
            int count = 0;
            List<ISNData> datas = new List<ISNData>();
            PropertyUtil.CollectFieldTypeValues<ISNData>(data, datas);
            foreach (ISNData sn in datas)
            {
                Type type = sn.GetType();
                HashMap<uint, ISNData> map = mSnDataMap.Get(type);
                if (map == null)
                {
                    map = new HashMap<uint, ISNData>();
                    mSnDataMap.Add(type, map);
                }
                if (!map.ContainsKey(sn.SerialNumber))
                {
                    map.Add(sn.SerialNumber, sn);
                    count++;
                }
                else
                {
                    throw new Exception(string.Format("SerialNumber {0} already in use ! {1}", sn.SerialNumber, sn));
                }
            }
            return count;
        }

        public int RehashAll()
        {
            mSnDataMap.Clear();
            int count = 0;
            count += Rehash(mUnits);
            count += Rehash(mSkills);
            count += Rehash(mSpells);
            count += Rehash(mBuffs);
            count += Rehash(mItems);
            count += Rehash(mUnitTriggers);
            count += Rehash(mUnitEvents);
            return count;
        }

        internal int RehashAllScene(object scenes)
        {
            return Rehash(scenes);
        }

        internal int RehashScene(object scene)
        {
            int count = 0;
            mCurrentSceneSnDataMap.Clear();
            List<ISNData> datas = new List<ISNData>();
            PropertyUtil.CollectFieldTypeValues<ISNData>(scene, datas);
            foreach (ISNData sn in datas)
            {
                if (!mCurrentSceneSnDataMap.ContainsKey(sn.SerialNumber))
                {
                    mCurrentSceneSnDataMap.Add(sn.SerialNumber, sn);
                    count++;
                }
                else
                {
                    throw new Exception(string.Format("SerialNumber {0} already in use ! {1} @ {2}", sn.SerialNumber, sn, scene));
                }
            }
            return count;
        }

        public T GetSnData<T>(uint sn) where T : ISNData
        {
            Type type = typeof(T);
            HashMap<uint, ISNData> map = mSnDataMap.Get(type);
            if (map != null)
            {
                T ret = map.Get(sn) as T;
                if (ret != null)
                {
                    return ret;
                }
            }
            T ret2 = mCurrentSceneSnDataMap.Get(sn) as T;
            if(ret2 == null)
            {
                //打一些Log,以免某些效果出不来,没头脑的找半天
                ClientLog.LogError("找不到SerialNumber={0}的数据,某些效果可能丢失,需要等待服务器更新", sn);
            }
            return ret2;
        }

    }

    public interface ITemplateData : IExternalizable
    {
        int TemplateID { get; }
        string EditorPath { get; set; }
    }
    public abstract class ISNData : IExternalizable
    {
        private static IDGenerator idgen = new IDGenerator();

        private uint mSN = idgen.NextID();

        [XmlSerializableAttribute(XmlSerializableProperty.IgnoreClone)]
        public uint SerialNumber
        {
            get { return mSN; }
            set { mSN = idgen.Regist(value); }
        }
        public void RegenSerialNumber(uint value)
        {
            mSN = idgen.Regist(value);
        }
        public virtual void WriteExternal(IOutputStream output)
        {
            output.PutU32(mSN);
        }
        public virtual void ReadExternal(IInputStream input)
        {
            this.mSN = input.GetU32();
        }
    }

}