using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using FObjBase;
using System.Net.Sockets;

namespace TCPManager
{
    //客户端长时间不通讯，必须发送 Send_HeartBeat
    public class TCPCConn : TCPConn
    {
        enum STATE
        {
            Connected,
            Not_Connect,
            Connecting,
            Err_Connect
        }

        private STATE state;
        private DateTime conn_delay_time;

        private IPEndPoint ep;
        public IPEndPoint RemoteEP
        {
            get
            {
                if (ep != null)
                    return new IPEndPoint(ep.Address, ep.Port);
                else
                    return null;
            }
            set
            {
                ep = new IPEndPoint(value.Address, value.Port);
            }
        }
        PollModule.PollHandler onpoll_func;

        public TCPCConn(IPEndPoint ipep, ParsePacketHandler func)
        {
            RemoteEP = ipep;
            onpoll_func = new PollModule.PollHandler(delegate()
            {
                OnPoll();
            });
            ParsePacket = func;
            ReStart();
        }


        void ReStart()
        {
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sock.Blocking = false;
            state = STATE.Not_Connect;
            PollModule.Current.Poll_Config(
                PollModule.POLL_CONFIG.ADD, onpoll_func, TimeSpan.FromMilliseconds(1));
        }
        protected override void Stop()
        {
            base.Stop();
            PollModule.Current.Poll_Config(
                PollModule.POLL_CONFIG.REMOVE, onpoll_func);
            IsConnected = false;
        }
        public override int OnPoll()
        {

            if (!Enable)
                return 0;

            switch (state)
            {
                case STATE.Not_Connect:
                    try
                    {
                        sock.Connect(RemoteEP);
                    }
                    catch (SocketException e)
                    {
                        if (e.SocketErrorCode != SocketError.WouldBlock)
                        {
                            conn_delay_time = DateTime.Now;
                            state = STATE.Err_Connect;
                            break;
                        }
                    }
                    conn_delay_time = DateTime.Now;
                    state = STATE.Connecting;
                    break;
                case STATE.Connecting:
                    if (sock.Connected)
                    {
                        state = STATE.Connected;
                        first_poll = true;
                        Init();
                        //连接成功
                        IsConnected = true;
                    }
                    else if (sock.Poll(0, SelectMode.SelectError))
                    {
                        state = STATE.Not_Connect;
                    }
                    break;
                case STATE.Connected:
                    {
                        if (base.OnPoll() < 0)
                        {
                            Enable = true;
                            ReStart();
                            state = STATE.Err_Connect;
                        }
                        break;
                    }
                case STATE.Err_Connect:
                    if ((DateTime.Now-conn_delay_time) > TimeSpan.FromMilliseconds(1000))
                        state = STATE.Not_Connect;
                    break;
            }
            return 0;
        }

    }
}
