using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GatewayCommon;
using System.ServiceModel;
using System.IO.Ports;
using System.Threading;

namespace WCF_duplex_server
{
    public delegate void GatewayServerStatusHandler(bool online);

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
    public class ServerControl : IServerMethods, IDisposable
    {
        public event GatewayServerStatusHandler StatusChange;

        private GatewayControl cc;
        private static Dictionary<Guid, IServerCallbacks> callbacks = new Dictionary<Guid, IServerCallbacks>();
        private bool isAlive = false;
        private SerialPort gatewaySerialPort = new SerialPort("COM4");
        public bool IsAlive
        {
            get
            {
                return isAlive;
            }
        }
        public SerialPort GatewaySerialPort
        {
            get
            {
                return gatewaySerialPort;
            }
            set
            {
                this.gatewaySerialPort = value;
            }
        }

        public ServerControl()
        {
            this.Open();
        }
        public ServerControl(SerialPort gatewaySerialPort)
        {
            this.gatewaySerialPort = gatewaySerialPort;
            this.Open();
        }
        ~ServerControl()
        {
            this.Close();
        }
        public void Dispose()
        {
            this.Close();
        }
        public void Open()
        {
            cc = new GatewayControl(gatewaySerialPort);
            cc.IncommingMessage += new GatewayControl.IncommingMessageHandler(cc_IncommingMessage);
            cc.IncommingCall += new GatewayControl.IncommingCallHandler(cc_IncommingCall);

            while (!GatewayPreSetting())
            {
                Thread.Sleep(200);
            }

            isAlive = true;
            if (StatusChange != null)
                StatusChange(isAlive);
        }
        public void Close()
        {
            isAlive = false;
            if (StatusChange != null)
                StatusChange(isAlive);
            if (cc.IsConnectionAlive)
                cc.Dispose();
        }

        public bool IsServerAlive()
        {
            return isAlive;
        }

        public void SubscribeCallback(Guid clientGuid)
        {
            callbacks.Add(clientGuid, OperationContext.Current.GetCallbackChannel<IServerCallbacks>());
        }
        public void UnsubscribeCallback(Guid clientGuid)
        {
            callbacks.Remove(clientGuid);
        }

        public bool Test()
        {
            if (cc.IsConnectionAlive)
            {
                if (cc.TestCommunication())
                    return true;
            }
            return false;
        }
        public string[] GetGatewayInformation()
        {
            if (cc.IsConnectionAlive)
            {
                return cc.GetGatewayInformation();
            }
            return null;
        }
        public int GetSignalStatus()
        {
            if (cc.IsConnectionAlive)
            {
                return cc.GetSignalStatus();
            }
            return 0;
        }
        public bool SendSMS(string phoneNumber, string smsMessage, bool approve)
        {
            if (cc.IsConnectionAlive)
            {
                if (cc.SendSMS(phoneNumber, smsMessage, approve))
                    return true;
            }
            return false;
        }
        public bool RingThePhone(string phoneNumber, bool approve)
        {
            if (cc.IsConnectionAlive)
            {
                if (cc.RingThePhone(phoneNumber, approve))
                    return true;
            }
            return false;
        }

        void cc_IncommingCall(int deviceId, string phoneNumber, DateTime incommingDate)
        {
            foreach (IServerCallbacks callback in callbacks.Values)
            {
                callback.IncommingCall(phoneNumber, incommingDate);
            }
        }
        void cc_IncommingMessage(int deviceId, string phoneNumber, string message, DateTime incommingDate)
        {
            foreach (IServerCallbacks callback in callbacks.Values)
            {
                callback.IncommingMessage(message, phoneNumber, incommingDate);
            }
        }

        private bool GatewayPreSetting()
        {
            if (cc.IsConnectionAlive)
            {
                if (!cc.SendCommand("AT+CLIP=1", new string[] { "OK" }))
                    return false;
                if (!cc.SendCommand("AT+CNMI=1,2,0,0,0", new string[] { "OK" }))
                    return false;
                if (!cc.SendCommand("AT+CMGF=1", new string[] { "OK" }))
                    return false;
                return true;
            }
            return false;
        }
    }
}
