using System;
using System.Collections.Generic;
using System.Text;
using Shared;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

namespace ChtiCanon
{
    /// <summary>
    /// Classe qui transformet les evenements reseau au reste du programme
    /// </summary>
    public class ConnectionManager
    {
        private event EventHandler<Message> _message;
        public event EventHandler<Message> message
        {
            add { _message += value; }
            remove { _message -= value; }
        }
        private event EventHandler<Users> _users;
        public event EventHandler<Users> users
        {
            add { _users += value; }
            remove { _users -= value; }
        }
        private event EventHandler<User> _winner;
        public event EventHandler<User> winner
        {
            add { _winner += value; }
            remove { _winner -= value; }
        }
        private event EventHandler<Shoot> _shoot;
        public event EventHandler<Shoot> shoot
        {
            add { _shoot += value; }
            remove { _shoot -= value; }
        }
        private event EventHandler<Angle> _angle;
        public event EventHandler<Angle> angle
        {
            add { _angle += value; }
            remove { _angle -= value; }
        }
        private event EventHandler<Game> _game;
        public event EventHandler<Game> game
        {
            add { _game += value; }
            remove { _game -= value; }
        }
        private event EventHandler<Round> _round;
        public event EventHandler<Round> round
        {
            add { _round += value; }
            remove { _round -= value; }
        }
        private NetworkStream ns;
        private BinaryFormatter bf = new BinaryFormatter();
        private int _ID;

        public int ID
        {
            get { return _ID; }
        }
        public ConnectionManager(IPAddress ip, int port)
        {
            TcpClient client = new TcpClient();
            client.Connect(ip, port);
            ns = client.GetStream();
            new Thread(new ThreadStart(delegate()
            {
                try
                {
                    while (true)
                    {
                        Object o = bf.Deserialize(ns);
                        if (o is Message)
                        {
                            while (_message == null) Thread.Sleep(100);
                            _message(this, (Message)o);
                        }
                        else if (o is Users)
                        {
                            while (_users == null) Thread.Sleep(100);
                            _users(this, (Users)o);
                        }
                        else if (o is User)
                        {
                            while (_winner == null) Thread.Sleep(100);
                            _winner(this, (User)o);
                        }
                        else if (o is Shoot)
                        {
                            while (_shoot == null) Thread.Sleep(100);
                            _shoot(this, (Shoot)o);
                        }
                        else if (o is Angle)
                        {
                            while (_angle == null) Thread.Sleep(100);
                            _angle(this, (Angle)o);
                        }
                        else if (o is Game)
                        {
                            while (_game == null) Thread.Sleep(100);
                            _game(this, (Game)o);
                        }
                        else if (o is Round)
                        {
                            while (_round == null) ;
                            _round(this, (Round)o);
                        }
                        else if (o is int) { _ID = (int)o; };
                    }
                }
                catch (Exception ex) { dead(ex); }
            })).Start();
        }
        /// <summary>
        /// Transmet des donnees au server
        /// </summary>
        /// <param name="o">Les donnees a transmettre</param>
        public void send(object o) { try { bf.Serialize(ns, o); } catch (Exception ex) { dead(ex); } }
        /// <summary>
        /// Ferme proprement le canal
        /// </summary>
        public void Close()
        {
            send(new Close());
            ns.Close();
        }
        /// <summary>
        /// Si la connection a pete, on tue tout
        /// </summary>
        /// <param name="ex">L'exception</param>
        private void dead(Exception ex)
        {
            System.Windows.Forms.MessageBox.Show("Server connection lost\n" + ex.Message, "ChtiCanon", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            Environment.Exit(1);
        }
    }
}
