﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;

namespace Gaazar
{ 
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class RPCMethodAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class RBCMethodAttribute : Attribute { }//Remote Broadcast Call

    [AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]
    public class SyncVarAttribute : Attribute
    {

    }

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class RemoteAttribute : ContextAttribute, IContributeObjectSink
{
    public RemoteAttribute() : base("Remote") { }

    /// <summary>
    /// 实现消息接收器接口
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="next"></param>
    /// <returns></returns>
    public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next) => new GaRPCHandler(next);
}
/// <summary>
/// AOP方法处理类,实现了IMessageSink接口
/// </summary>
public sealed class GaRPCHandler : IMessageSink
{
    /// <summary>
    /// 下一个接收器
    /// </summary>
    public IMessageSink NextSink { get; private set; }
    public GaRPCHandler(IMessageSink nextSink)
    {
        this.NextSink = nextSink;
    }

    /// <summary>
    /// 同步处理方法
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    public IMessage SyncProcessMessage(IMessage msg)
    {
        //方法调用消息接口
        var call = msg as IMethodCallMessage;
        //只拦截指定方法,其它方法原样释放
        if (call == null || Attribute.GetCustomAttribute(call.MethodBase, typeof(RBCMethodAttribute)) == null) return NextSink.SyncProcessMessage(msg);
        //判断第2个参数,如果是0,则强行返回100,不调用方法了
        if (((int)call.InArgs[1]) == 0) return new ReturnMessage(100, call.Args, call.ArgCount, call.LogicalCallContext, call);

        //判断第2个参数,如果是1,则参数强行改为50(失败了)
        //if (((int)call.InArgs[1]) == 1) call = new MyCall(call, call.Args[0], 50);//方法1  失败了
        //if (((int)call.InArgs[1]) == 1) call.MethodBase.Invoke(GetUnwrappedServer(), new object[] { call.Args[0], 50 });//方法2 (无法凑够参数)
        var retMsg = NextSink.SyncProcessMessage(call);
        //判断返回值,如果是5,则强行改为500
        if (((int)(retMsg as IMethodReturnMessage).ReturnValue) == 5) return new ReturnMessage(500, call.Args, call.ArgCount, call.LogicalCallContext, call);

        return retMsg;
    }

    /// <summary>
    /// 异步处理方法(暂不处理)
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replySink"></param>
    /// <returns></returns>
    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) => null;
}
}