using System;
using System.Collections.Generic;
using System.Reflection;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;


namespace SiaSun.LMS.WCFHost
{
    public class ServiceHostGroup
    {
        public static List<ServiceHost> _hosts = new List<ServiceHost>();

        /// <summary>
        /// ¿ªÊ¼·þÎñ
        /// </summary>
        private static void OpenHost(Type t, string iType, string url,string binding)
        {
            ServiceHost hst = new ServiceHost(t, new Uri(string.Format(url, MainApp._BaseUrl)));
            ServiceThrottlingBehavior throttlingBehavior = hst.Description.Behaviors.Find<ServiceThrottlingBehavior>();
            if (throttlingBehavior == null)
            {
                throttlingBehavior = new ServiceThrottlingBehavior { MaxConcurrentCalls = 3000, MaxConcurrentSessions = 3000 };
                hst.Description.Behaviors.Add(throttlingBehavior);
            }
            else
            {
                throttlingBehavior.MaxConcurrentCalls = 3000;
                throttlingBehavior.MaxConcurrentSessions = 3000;
            }

            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            hst.Description.Behaviors.Add(smb);

            hst.AddServiceEndpoint(iType, SiaSun.LMS.Common.WCFHelper.CreateBinding(binding), "");
            hst.Open();
            _hosts.Add(hst);
        }

        /// <summary>
        /// Æô¶¯ËùÓÐÅäÖÃÎļþÖеķþÎñ
        /// </summary>
        public static void StartAllConfiguredServices(ref IList<ServiceModel.WCFService> ServiceList)
        {
            //¶ÁÈ¡ÅäÖÃÎļþ
            ConfiguredServices services = ConfiguredServices.LoadFromFile("services.xml");
            //±éÀúÅäÖÃÎļþÖеķþÎñÐÅÏ¢
            foreach (ConfiguredService svc in services.Services)
            {
                string svcIType = svc.iType;
                string binding = svc.binding;
                string url = svc.URL;
                string strAddress = new Uri(string.Format(url, MainApp._BaseUrl)).AbsoluteUri;
                ServiceModel.WCFService service = null;
                
                try
                {
                    //»ñµÃ·þÎñÀàÐÍ
                    Type svcType = Type.GetType(svc.Type);
                    if (svcType == null)
                    {
                        MAIN.mainWin.AddMessage(string.Format("{0},{1}",svc.Type.ToString(), "»ñµÃWCF·þÎñÀàÐÍʧ°Ü£¡"));
                        continue;
                    }

                    //Ìí¼Ó¼Ç¼
                    if (ServiceList.Count(r => r.WCFServiceName == svc.Type) == 0)
                    {
                        service = new ServiceModel.WCFService(svcType.Name, "Æô¶¯", strAddress, string.Empty);
                        ServiceList.Add(service);
                    }
                    else
                    {
                        //»ñµÃ²¢¸ü¸Ä״̬ºÍÏûÏ¢
                        service = ServiceList.First(r => r.WCFServiceName == svc.Type);
                    }

                    //´ò¿ª·þÎñ
                    OpenHost(svcType, svcIType, url, binding);             
                }
                catch(Exception ex)
                {
                    if (service != null)
                    {
                        service.WCFServiceStatus = "Í£Ö¹";
                    }
                    throw new Exception(string.Format("{0},{1}", svc.Type.ToString(), ex.Message));
                }
            }
        }

        /// <summary>
        /// ¹Ø±ÕËùÓзþÎñ
        /// </summary>
        public static void CloseAllServices(ref IList<ServiceModel.WCFService> ServiceList)
        {
            foreach (ServiceHost hst in _hosts)
            {
                if (ServiceList.Count(r => r.WCFServiceName == hst.Description.ServiceType.Name) > 0)
                {
                    hst.Close();
                    ServiceList.First(r => r.WCFServiceName == hst.Description.ServiceType.Name).WCFServiceStatus = "Í£Ö¹";
                }
            }
        }
    }

    [XmlRoot("configuredServices")]
    public class ConfiguredServices
    {
        public static ConfiguredServices LoadFromFile(string filename)
        {
            if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + filename)) return new ConfiguredServices();

            XmlSerializer ser = new XmlSerializer(typeof(ConfiguredServices));

            using (FileStream fs = File.OpenRead(AppDomain.CurrentDomain.BaseDirectory + filename))
            {
                return (ConfiguredServices)ser.Deserialize(fs);
            }
        }

        [XmlElement("service", typeof(ConfiguredService))]
        public List<ConfiguredService> Services = new List<ConfiguredService>();
    }

    public class ConfiguredService
    {
        [XmlAttribute("type")]
        public string Type;

        [XmlAttribute("itype")]
        public string iType;

        [XmlAttribute("binding")]
        public string binding;

        [XmlAttribute("url")]
        public string URL;
    }
}