using System;
using System.ServiceModel;

namespace GatewayAPI
{
    public delegate void GatewayMessageHandler(string message, string phone, DateTime incommingTime);
    public delegate void GatewayCallHandler(string phone, DateTime incommingTime);

    public class GatewayClientCallbackAPI : IServerCallbacks
    {
        public event GatewayMessageHandler NewMessage;
        public event GatewayCallHandler NewCall;

        public void IncommingMessage(string message, string phone, DateTime time)
        {
            if (NewMessage != null)
                NewMessage(message, phone, time);
        }
        public void IncommingCall(string phone, DateTime time)
        {
            if (NewCall != null)
                NewCall(phone, time);
        }
    }

    public class GatewayClientAPI : IDisposable
    {
        public event GatewayMessageHandler NewMessage;
        public event GatewayCallHandler NewCall;

        private DuplexChannelFactory<IServerMethods> cf;
        private IServerMethods server;
        private GatewayClientCallbackAPI callback;

        private Guid clientGuid;
        private string ipAddress = "localhost";
        private string port = "9080";
        private bool isConnected = false;

        public bool IsConnected
        {
            get
            {
                return isConnected;
            }
        }

        public GatewayClientAPI()
        {
            this.Open();
        }
        public GatewayClientAPI(Guid clientGuid)
        {
            this.clientGuid = clientGuid;
            this.Open();
        }
        public GatewayClientAPI(string ipAddress, string port)
        {
            this.ipAddress = ipAddress;
            this.port = port;
            this.Open();
        }
        public GatewayClientAPI(Guid clientGuid, string ipAddress, string port)
        {
            this.clientGuid = clientGuid;
            this.ipAddress = ipAddress;
            this.port = port;
            this.Open();
        }
        ~GatewayClientAPI()
        {
            this.Close();
        }
        public void Dispose()
        {
            this.Close();
        }

        public void Open()
        {
            callback = new GatewayClientCallbackAPI();
            callback.NewCall += new GatewayCallHandler(callback_NewCall);
            callback.NewMessage += new GatewayMessageHandler(callback_NewMessage);
            clientGuid = Guid.NewGuid();
            cf = new DuplexChannelFactory<IServerMethods>(callback, new NetTcpBinding(), new EndpointAddress("net.tcp://" + ipAddress + ":" + port + "/GatewayCommunication"));
            if (cf.Endpoint != null)
            {
                server = cf.CreateChannel();
                server.SubscribeCallback(clientGuid);
                isConnected = true;
            }
        }
        public void Close()
        {
            if (cf != null)
            {
                isConnected = false;
                server.UnsubscribeCallback(clientGuid);
                cf.Abort();
                cf.Close();
                cf = null;
            }
        }

        public bool Test()
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.Test();
                }
                catch (Exception) { }
            }
            return false;
        }
        public string[] GetGatewayInformation()
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.GetGatewayInformation();
                }
                catch (Exception) { }
            }
            return null;

        }
        public int GetSignalStatus()
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.GetSignalStatus();
                }
                catch (Exception) { }
            }
            return 0;
        }
        public bool SendSMS(string phoneNumber, string smsMessage)
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.SendSMS(phoneNumber, smsMessage, false);
                }
                catch (Exception) { }
            }
            return false;
        }
        public bool SendSMS(string phoneNumber, string smsMessage, bool approve)
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.SendSMS(phoneNumber, smsMessage, approve);
                }
                catch (Exception) { }
            }
            return false;
        }
        public bool RingThePhone(string phoneNumber)
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.RingThePhone(phoneNumber, false);
                }
                catch (Exception) { }
            }
            return false;
        }
        public bool RingThePhone(string phoneNumber, bool approve)
        {
            if (server.IsServerAlive())
            {
                try
                {
                    return server.RingThePhone(phoneNumber, approve);
                }
                catch (Exception) { }
            }
            return false;
        }


        static public bool SendSMS(string ipAddress, string port, string phoneNumber, string smsMessage)
        {
            using (GatewayClientAPI gca = new GatewayClientAPI(ipAddress, port))
            {
                if (gca.SendSMS(phoneNumber, smsMessage))
                    return true;
            }
            return false;
        }
        static public bool SendSMS(string ipAddress, string port, string phoneNumber, string smsMessage, bool approve)
        {
            using (GatewayClientAPI gca = new GatewayClientAPI(ipAddress, port))
            {
                if (gca.SendSMS(phoneNumber, smsMessage, approve))
                    return true;
            }
            return false;
        }
        static public bool RingThePhone(string ipAddress, string port, string phoneNumber)
        {
            using (GatewayClientAPI gca = new GatewayClientAPI(ipAddress, port))
            {
                if (gca.RingThePhone(phoneNumber))
                    return true;
            }
            return false;
        }
        static public bool RingThePhone(string ipAddress, string port, string phoneNumber, bool approve)
        {
            using (GatewayClientAPI gca = new GatewayClientAPI(ipAddress, port))
            {
                if (gca.RingThePhone(phoneNumber, approve))
                    return true;
            }
            return false;
        }

        void callback_NewMessage(string message, string phone, DateTime incommingTime)
        {
            if (NewMessage != null)
                NewMessage(message, phone, incommingTime);
        }
        void callback_NewCall(string phone, DateTime incommingTime)
        {
            if (NewCall != null)
                NewCall(phone, incommingTime);
        }
    }
}
