using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FObjBase
{
    public interface IFObj: IDisposable
    {
        FObjSys CurrObjSys { get; }
        /// <summary>
        /// OBJID
        /// 作为对外的接口，ID必须明确定义好，应该在构造函数时，作为参数传入；
        /// 对应只用于代理，ID按顺序排序，顺便。。。
        /// </summary>
        UInt32 ID { get; set; }

        /// <summary>
        /// 通知连接成功，失败
        /// </summary>
        /// <param name="from">远端对应的连接代理, 里面有IP, 连接的状态</param>
        void ConnectNotify(IFConn from);


        /// <summary>
        /// 自己解析远端的数据;
        /// 当ProcessEx返回 非0, 系统解析数据，对应调用GetValue,SetValue,CallFunction,PushInfo
        /// 建议都返回 非0
        /// </summary>
        /// <param name="from">远端对应的连接代理</param>
        /// <param name="srcid">远端的OBJID</param>
        /// <param name="magic">交易码</param>
        /// <param name="info_no">信息码</param>
        /// <param name="infodata">信息内容</param>
        /// <param name="retdata">返回数据</param>
        /// <returns>0:成功;非0:不支持</returns>
        int ProcessEx(IFConn from, UInt32 srcid, UInt32 magic, UInt16 info_no, byte[] infodata, out byte[] retdata);

        #region Server->Client
        /// <summary>
        /// 作为客户端， 服务器回复GetValue
        /// </summary>
        /// <param name="from">与服务器的连接代理</param>
        /// <param name="srcid">服务器的OBJID</param>
        /// <param name="memid">成员ID</param>
        /// <param name="infodata">成员数据</param>
        void PushGetValue(IFConn from, UInt32 srcid, UInt16 memid, byte[] infodata);

        /// <summary>
        /// 作为客户端， 服务器回复CallFunction
        /// </summary>
        /// <param name="from">与服务器的连接代理</param>
        /// <param name="srcid">服务器的OBJID</param>
        /// <param name="magic">交易号</param>
        /// <param name="funcid">功能ID</param>
        /// <param name="retdata">回复的数据</param>
        /// <param name="asyncDelegate">以前客户端调用CallFunction时，放入的函数指针</param>
        /// <param name="asyncContext">以前客户端调用CallFunction时，放入的object</param>
        void PushCallFunction(IFConn from, UInt32 srcid, UInt32 magic, UInt16 funcid, byte[] retdata,AsyncCBHandler asyncDelegate, object asyncContext);

        /// <summary>
        /// 远端消息推送到本地
        /// </summary>
        /// <param name="from">远端对应的连接代理</param>
        /// <param name="srcid">远端的OBJID</param>
        /// <param name="infoid">消息ID</param>
        /// <param name="infodata">消息数据</param>
        void PushInfo(IFConn from, UInt32 srcid, UInt16 infoid, byte[] infodata);

        /// <summary>
        /// 作为客户端， 服务器回复CallFunction， 回复数据为大包，显示进度
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="magic"></param>
        /// <param name="funcid"></param>
        /// <param name="total_size"></param>
        /// <param name="download_size"></param>
        /// <param name="asyncContext"></param>
        void PushCallFunctionBigSizeStatus(IFConn from, UInt32 srcid, UInt32 magic, UInt16 funcid, int total_size, int download_size, object asyncContext);
        #endregion

        #region Client->Server
        /// <summary>
        /// 远端获取本地成员数据
        /// </summary>
        /// <param name="from">远端对应的连接代理</param>
        /// <param name="srcid">远端的OBJID</param>
        /// <param name="memid">成员ID</param>
        /// <param name="infodata">成员数据</param>
        void GetValue(IFConn from,UInt32 srcid,UInt16 memid,out byte[] infodata);

        /// <summary>
        /// 远端设置本地成员数据
        /// </summary>
        /// <param name="from">远端对应的连接代理</param>
        /// <param name="srcid">远端的OBJID</param>
        /// <param name="memid">成员ID</param>
        /// <param name="infodata">成员数据</param>
        void SetValue(IFConn from,UInt32 srcid,UInt16 memid,byte[] infodata);

        /// <summary>
        /// 远端执行本地函数， 如果有数据返回，需要自己 SendMessageEx
        /// </summary>
        /// <param name="from">远端对应的连接代理</param>
        /// <param name="srcid">远端的OBJID</param>
        /// <param name="magic">交易号</param>
        /// <param name="funcid">函数ID</param>
        /// <param name="infodata">参数</param>
        void CallFunction(IFConn from, UInt32 srcid, UInt32 magic, UInt16 funcid, byte[] infodata);

        #endregion

    }
    /// <summary>
    /// obj 会自动加入到 objsys中，ID也会自动按顺序分配，也可以手动修改，但都应该在构造函数完成
    /// </summary>
    public class FObj : IFObj 
    {
        public FObj()
        {
            ID = 0;
            CurrObjSys.ObjAdd(this);
        }
        public FObj(int objsys_idx) 
        {
            ID = 0;
            this.objsys_idx = objsys_idx;
            CurrObjSys.ObjAdd(this);
        }
        #region IFObj 成员

        private int objsys_idx=0;
        public FObjSys CurrObjSys {
            get {
                return FObjSys.Currents[objsys_idx];
            }
        }
        public virtual uint ID
        {
            get;
            set;
        }

        /// <summary>
        /// 连接通知事件
        /// </summary>
        /// <param name="from"></param>
        public virtual void ConnectNotify(IFConn from)
        {
            
        }

        public virtual int ProcessEx(IFConn from, uint srcid, uint magic, ushort info_no, byte[] infodata, out byte[] retdata)
        {
            retdata = null;
            return -1;
        }
        #region Server->Client
        /// <summary>
        /// 作为客户端 接收服务器 GetValue 回复
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="memid"></param>
        /// <param name="infodata"></param>
        public virtual void PushGetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {

        }

        /// <summary>
        /// 作为客户端 接收服务器 CallFunction 回复
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="magic"></param>
        /// <param name="funcid"></param>
        /// <param name="retdata"></param>
        /// <param name="asyncDelegate"></param>
        /// <param name="asyncContext"></param>
        public virtual void PushCallFunction(IFConn from, uint srcid, UInt32 magic, ushort funcid, byte[] retdata, AsyncCBHandler asyncDelegate, object asyncContext)
        {
        }

        /// <summary>
        /// 作为客户端 接收服务器 PushInfo 推送事件
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="infoid"></param>
        /// <param name="infodata"></param>
        public virtual void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
        }

        /// <summary>
        /// 作为客户端， 服务器回复CallFunction， 回复数据为大包，显示进度
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="magic"></param>
        /// <param name="funcid"></param>
        /// <param name="total_size"></param>
        /// <param name="download_size"></param>
        /// <param name="asyncContext"></param>
        public virtual void PushCallFunctionBigSizeStatus(IFConn from, UInt32 srcid, UInt32 magic, UInt16 funcid, int total_size, int download_size, object asyncContext)
        {

        }
        #endregion
        #region Client->Server
        /// <summary>
        /// 作为服务器， 接收从客户端发送过来的 GetValue 请求
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="memid"></param>
        /// <param name="infodata"></param>
        public virtual void GetValue(IFConn from, uint srcid, ushort memid, out byte[] infodata)
        {
            infodata = null;
        }

        /// <summary>
        /// 作为服务器， 接收从客户端发送过来的 SetValue 请求
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="memid"></param>
        /// <param name="infodata"></param>
        public virtual void SetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
        }

        /// <summary>
        ///  作为服务器， 接收从客户端发送过来的 CallFunction 请求
        /// </summary>
        /// <param name="from"></param>
        /// <param name="srcid"></param>
        /// <param name="magic"></param>
        /// <param name="funcid"></param>
        /// <param name="infodata"></param>
        public virtual void CallFunction(IFConn from, uint srcid, UInt32 magic, ushort funcid, byte[] infodata)
        {
        }
        #endregion

        #endregion

        #region IDisposable 成员

        public virtual void Dispose()
        {
            CurrObjSys.ObjRemove(this);
        }

        #endregion
    }
}
