using CommonAI.Zone;
using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using CommonAIServer.Connector.Client;
using CommonLang;
using CommonLang.Concurrent;
using CommonLang.Log;
using CommonLang.Property;
using CommonLang.Protocol;
using CommonNetwork.Sockets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonAIServer.Connector.Bot
{
    public class BotRunner
    {
        public static BotRunner Instance { get; private set; }
        public static InstanceZoneFactory ZoneFactory { get; private set; }
        public static MessageFactoryGenerator MessageFactory { get; private set; }
        public static EditorTemplates Templates { get; private set; }
        public static string ConnectString { get; private set; }

        private Logger log = LoggerFactory.GetLogger("BotRunner");

        public bool IsRunning { get; private set; }

        public BotRunner(string factoryClass, string dataRoot, string connectString)
        {
            log.Info("********************************************************");
            log.Info("# 初始化");
            log.Info("********************************************************");
            
            ZoneFactory = ReflectionUtil.CreateInterface<InstanceZoneFactory>(factoryClass);
            TemplateManager.setFactory(ZoneFactory);
            log.Info(" 战斗编辑器插件 --> " + ZoneFactory);
            MessageFactory = TemplateManager.MessageCodec;
            log.Info("\r\n" + MessageFactory.ListAll("  "));
            Templates = new EditorTemplates(dataRoot, MessageFactory);
            EditorTemplates.DEFAULT_LOAD_FROM_BIN = true;
            Templates.LoadAllTemplates();
            ConnectString = connectString; ;
            Instance = this;
        }

        public void Start()
        {
            this.IsRunning = true;
        }

        public void Shutdown()
        {
            this.IsRunning = false;
        }


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

        private AtomicInteger test_player_indexer = new AtomicInteger(0);
        private HashMap<string, BotPlayer> Bots = new HashMap<string, BotPlayer>();
        private Random random = new Random();

        public List<BotPlayer> BotsList { get { lock (Bots) { return new List<BotPlayer>(Bots.Values); } } }
        public int BotsCount { get { lock (Bots) { return Bots.Count; } } }

        public string BotsStatus
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                foreach (BotPlayer bot in BotsList)
                {
                    sb.AppendLine(string.Format("Bot[{0}] IsRunning={1}", bot.Name, bot.IsRunning));
                }
                return sb.ToString();
            }
        }

        public BotPlayer AddBot(int force, List<int> templates)
        {
            int templateID = CUtils.GetRandomInArray(templates, random);
            UnitInfo unit = Templates.Templates.getUnit(templateID);
            if (unit == null)
            {
                log.Error("没有测试单位!");
                return null;
            }
            string name = unit.Name + "_" + test_player_indexer.IncrementAndGet();
            BotPlayer ret = null;
            lock (Bots)
            {
                if (Bots.ContainsKey(name))
                {
                    log.ErrorFormat("已包含单位[{0}]!", name);
                    return null;
                }
                ret = new BotPlayer(name, "", unit, force, Templates, ConnectString);
                Bots.Add(name, ret);
                log.InfoFormat("已添加单位: {0}", name);
            }
            ret.Start();
            return ret;
        }
        public void AddBots(int count, int force, List<int> templates = null)
        {
            for (int i = 0; i < count; i++)
            {
                AddBot(force, templates);
            }
        }
        public void CleanupBots()
        {
            foreach (BotPlayer bot in BotsList)
            {
                if (!bot.IsRunning)
                {
                    lock (Bots)
                    {
                        Bots.Remove(bot.Name);
                    }
                    bot.Dispose();
                }
            }
        }
        public void StopAllBots()
        {
            foreach (BotPlayer bot in BotsList)
            {
                bot.SendLeaveRoom();
            }
            CleanupBots();
        }
        public void StopBot(BotPlayer bot)
        {
            bot.SendLeaveRoom();
            CleanupBots();
        }
    }

}