using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Top.Api.Cluster
{
    public sealed class ClusterManager
    {
        private static readonly Random random = new Random();
        private static readonly Object initLock = new Object();
        private static volatile DnsConfig dnsConfig = null;
        private static volatile Thread refreshThread = null;

        public static T GetElementByWeight<T>(List<T> list) where T : Weightable
        {
            T selected = null;
            double totalWeight = 0d;
            foreach (T element in list)
            {
                double r = random.NextDouble() * (element.Weight + totalWeight);
                if (r >= totalWeight)
                {
                    selected = element;
                }
                totalWeight += element.Weight;
            }
            return selected;
        }

        public static DnsConfig GetDnsConfigFromCache()
        {
            return dnsConfig;
        }

        public static void InitRefreshThread(ITopClient client)
        {
            if (refreshThread == null)
            {
                lock (initLock)
                {
                    if (refreshThread == null)
                    {
                        try
                        {
                            DnsConfig remoteConfig = GetDnsConfigFromTop(client);
                            if (dnsConfig == null)
                            {
                                dnsConfig = remoteConfig;
                            }
                            else if (remoteConfig != null && remoteConfig.GetVersion() > dnsConfig.GetVersion())
                            {
                                dnsConfig = remoteConfig;
                            }
                        }
                        catch (TopException e)
                        {
                            if ("22".Equals(e.ErrorCode))
                            {
                                return; // 如果HTTP DNS服务不存在，则退出守护线程
                            }
                        }

                        refreshThread = new Thread(o =>
                        {
                            while (true)
                            {
                                try
                                {
                                    Thread.Sleep(dnsConfig.GetRefreshInterval() * 60 * 1000);
                                    dnsConfig = GetDnsConfigFromTop(client);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e.StackTrace);
                                    Thread.Sleep(3 * 1000); // 出错则过3秒重试
                                }
                            }
                        });
                        refreshThread.IsBackground = true;
                        refreshThread.Name = "HTTP_DNS_REFRESH_THREAD";
                        refreshThread.Start();
                    }
                }
            }
        }

        private static DnsConfig GetDnsConfigFromTop(ITopClient client)
        {
            HttpdnsGetRequest req = new HttpdnsGetRequest();
            HttpdnsGetResponse rsp = client.Execute(req);
            if (!rsp.IsError)
            {
                return DnsConfig.parse(rsp.Result);
            }
            else
            {
                throw new TopException(rsp.ErrCode, rsp.ErrMsg);
            }
        }
    }
}
