using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.Scene;
using CommonAI.Zone.ZoneEditor;
using XmdsCommonServer.Plugin.Quest;
using CommonLang;
using CommonAI.ZoneClient;
using CommonAI.RTS.Manhattan;
using XmdsCommon.ZoneClient;
using CommonAI.Data;

namespace XmdsCommonServer.Plugin
{
    /// <summary>
    /// FileName: XmdsZoneFactory.cs
    /// Author: Alex.Yu
    /// Corporation:... 
    /// Description: 
    /// DateTime: 2015/1/26 16:15:25
    /// </summary>
    public class XmdsZoneServerFactory : XmdsZoneFactory
    {
        private XmdsFormula mFormula = new XmdsFormula();
        public override CommonAI.Zone.Formula.IFormula Formula
        {
            get { return mFormula; }
        }

        public XmdsZoneServerFactory()
        {
        }

        public override EditorScene CreateEditorScene(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData createData, string bindGameSrvId)
        {
            return XmdsSceneFactory.CreateScene(templates, listener, data, createData, bindGameSrvId);
        }

        public override CommonAI.Zone.Helper.IQuestAdapter CreateQuestAdapter(CommonAI.Zone.Instance.InstanceZone zone)
        {
            return new XmdsQuestAdapter(zone as XmdsServerScene);
        }

        public override CommonAI.Zone.Formula.IVirtualUnit CreateUnitVirtual(InstanceUnit owner)
        {
            XmdsVirtual ret = null;

            if (owner is XmdsInstanceMonster)
            {
                ret = new XmdsVirtual_Monster(owner as XmdsInstanceMonster);
            }
            else if (owner is XmdsInstancePlayer)
            {
                ret = new XmdsVirtual_Player(owner as XmdsInstancePlayer);
            }
            else if (owner is XmdsInstanceNPC)
            {
                ret = new XmdsVirtual_NPC(owner as XmdsInstanceNPC);
            }
            else if (owner is XmdsInstanceSummonUnit)
            {
                ret = new XmdsVirtual_SummonUnit(owner as XmdsInstanceSummonUnit);
            }
            else if (owner is XmdsInstancePet)
            {
                ret = new XmdsVirtual_Pet(owner as XmdsInstancePet);
            }
            else
            {
                ret = new XmdsVirtual(owner);
            }

            return ret;
        }

        public override InstanceUnit CreateUnit(InstanceZone zone, UnitInfo info, string name, int force, int alliesForce, int level)
        {
            XmdsUnitProperties unit_prop = info.Properties as XmdsUnitProperties;
            switch (info.UType)
            {
                case UnitInfo.UnitType.TYPE_NEUTRALITY:
                case UnitInfo.UnitType.TYPE_NPC:
                    return new XmdsInstanceNPC(zone, info, name, force, level);
                case UnitInfo.UnitType.TYPE_SUMMON:
                    return new XmdsInstanceSummonUnit(zone, info, name, force, level);
                case UnitInfo.UnitType.TYPE_MONSTER:
                    return new XmdsInstanceMonster(zone, info, name, force, level);
                case UnitInfo.UnitType.TYPE_PLAYER:
                    return new XmdsInstancePlayer(zone, info, name, force, alliesForce, level);
                case UnitInfo.UnitType.TYPE_PET:
                    return new XmdsInstancePet(zone, info, name, force, level);
            }

            return base.CreateUnit(zone, info, name, force, alliesForce, level);
        }
        public override InstanceItem CreateItem(
            InstanceZone zone,
            ItemTemplate item,
            string name,
            int force,
            InstanceUnit creater,
			string disPlayName,
            int from)
        {
            return new XmdsDropableInstanceItem(zone, item, name, force, creater, disPlayName);
        }
        public override HateSystem CreateHateSystem(InstanceUnit owner)
        {
            return ((owner.Virtual as XmdsVirtual)).GetHateSystem();
        }

        public static XmdsVirtual ToVirtual(InstanceUnit unit)
        {
            return (unit.Virtual as XmdsVirtual);
        }








        //---------------------------------------------------------------------------------------------
        #region Client
            
        public static bool ClientSaveMemory
        {
            get { return s_save_memory; }
            set
            {
                s_save_memory = value;
                lock (s_maps)
                {
                    if (value == false)
                    {
                        s_maps.Clear();
                    }
                }
            }
        }
        private static HashMap<int, BotMapInfo> s_maps = new HashMap<int, BotMapInfo>();
        private static bool s_save_memory = true;

        public override ZoneLayer CreateClientZoneLayer(EditorTemplates templates, ILayerClient listener)
        {
            return new BotZoneLayer(templates, listener);
        }
        class BotZoneLayer : HZZoneLayer
        {
            public BotZoneLayer(EditorTemplates dataroot, ILayerClient client)
                : base(dataroot, client)
            {
            }
            protected override void InitTerrain(ClientEnterScene msg, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen)
            {
                if (ClientSaveMemory)
                {
                    BotMapInfo minfo = null;
                    lock (s_maps)
                    {
                        minfo = s_maps.Get(this.Data.ID);
                        if (minfo == null)
                        {
                            minfo = new BotMapInfo(base.TerrainSrc.Clone() as ZoneInfo, base.Templates);
                            s_maps.Add(this.Data.ID, minfo);
                        }
                    }
                    terrain_data = minfo.terrain_data;
                    path_finder = minfo.path_finder;
                    area_gen = minfo.area_gen;
                    //Data.Terrain = null;
                    this.IsShareTerrain = true;
                    this.IsIgnoreTerrainTouch = true;
                }
                else
                {
                    base.InitTerrain(msg, out terrain_data, out path_finder, out area_gen);
                }
            }
            protected override void DisposeTerrain()
            {
                if (ClientSaveMemory)
                {
                }
                else
                {
                    base.DisposeTerrain();
                }
            }
        }
        class BotMapInfo
        {
            public readonly BotLayerManhattanMap terrain_data;
            public readonly AstarManhattan path_finder;
            public readonly ManhattanMapAreaGenerator area_gen;
            public BotMapInfo(ZoneInfo data, TemplateManager templates)
            {
                this.terrain_data = new BotLayerManhattanMap(templates, data);
                this.path_finder = new AstarManhattan(data.TemplateID, terrain_data, true, 0);
                this.area_gen = new ManhattanMapAreaGenerator(terrain_data.Data);
            }
        }
        class BotLayerManhattanMap : ZoneManhattanMap
        {
            public BotLayerManhattanMap(TemplateManager templates, ZoneInfo info)
                : base(info, templates.TerrainDefinition)
            {
            }
            public override bool SetValue(int bx, int by, int value)
            {
                return false;
            }
        }

        #endregion
    }


}