using System;
using Cysharp.Threading.Tasks;

namespace KYFramework.Network
{
	public abstract class AMRpcHandler<Request, Response>: IMHandler where Request : class, IRequest where Response : class, IResponse 
	{
		protected abstract UniTask Run(Session session, Request message, Response response, Action reply);
		
		public void Handle(Session session, object message)
		{
			HandleAsync(session, message).Forget();
		}

		public Type GetMessageType()
		{
			return typeof (Request);
		}

		public async UniTask HandleAsync(Session session, object message)
		{
			try
			{
				Request request = message as Request;
				if (request == null)
				{
					Log.Error($"消息类型转换错误: {message.GetType().Name} to {typeof (Request).Name}");
				}

				int rpcId = request.RpcId;

				long instanceId = session.InstanceId;

				Response response = Activator.CreateInstance<Response>();

				void Reply()
				{
					if(session.InstanceId != instanceId)
						return;
					response.RpcId = rpcId;
					session.Reply(response);
				}

				try
				{
					await this.Run(session, request, response, Reply);
				}
				catch (Exception exception)
				{
					Log.Error(exception);
					response.Message = exception.ToString();
					Reply();
				}
			}
			catch (Exception e)
			{
				throw new Exception($"解释消息失败: {message.GetType().FullName}", e);
			}
		}
		
	}
}