
import clr
import sys
import os
import System
from System import String
from System.Collections.Generic import Dictionary

def compile_and_test():
    # DLLパスの設定
    dll_dir = os.path.join(os.getcwd(), "libs")
    sys.path.append(dll_dir)
    rapi_path = os.path.join(dll_dir, "rapiplus.dll")
    
    if not os.path.exists(rapi_path):
        print(f"Error: {rapi_path} not found")
        return

    # 参照の追加
    clr.AddReference("System")
    clr.AddReference("System.Runtime")
    clr.AddReference("rapiplus")
    
    import com.omnesys.rapi as rapi

    # C# コードの定義（強化版）
    csharp_code = """
    using System;
    using com.omnesys.rapi;

    namespace RithmicBridge.Wrapper
    {
        public class BridgeAdmCallbacks : AdmCallbacks
        {
            public Action<AlertInfo> OnAlert;
            public Action<Object> OnEnvironmentList;

            public override void Alert(AlertInfo oInfo)
            {
                if (OnAlert != null) OnAlert(oInfo);
            }

            public override void EnvironmentList(EnvironmentListInfo oInfo)
            {
               // if (OnEnvironmentList != null) OnEnvironmentList(oInfo);
            }
            
            public override void Environment(EnvironmentInfo oInfo) {}
            public override bool Equals(object obj) { return base.Equals(obj); }
            public override int GetHashCode() { return base.GetHashCode(); }
            public override string ToString() { return base.ToString(); }
        }

        public class BridgeRCallbacks : RCallbacks
        {
            public Action<DboInfo> OnDbo;
            public Action<TradeInfo> OnTradePrint;

            public override void Dbo(DboInfo oInfo)
            {
                if (OnDbo != null) OnDbo(oInfo);
            }

            public override void TradePrint(TradeInfo oInfo)
            {
                if (OnTradePrint != null) OnTradePrint(oInfo);
            }

            public override bool Equals(object obj) { return base.Equals(obj); }
            public override int GetHashCode() { return base.GetHashCode(); }
            public override string ToString() { return base.ToString(); }
        }
    }
    """

    # ... (コンパイル部分は同じ) ...

    try:
        from System.CodeDom.Compiler import CodeDomProvider, CompilerParameters
        
        provider = CodeDomProvider.CreateProvider("CSharp")
        params = CompilerParameters()
        params.GenerateInMemory = True
        params.ReferencedAssemblies.Add("System.dll")
        params.ReferencedAssemblies.Add(rapi_path)
        
        results = provider.CompileAssemblyFromSource(params, csharp_code)
        
        if results.Errors.HasErrors:
            print("Compilation Errors:")
            for error in results.Errors:
                print(f"  {error.ErrorText}")
            return

        print("Compilation Success!")
        assembly = results.CompiledAssembly
        
        # インスタンス化テスト
        t_adm = assembly.GetType("RithmicBridge.Wrapper.BridgeAdmCallbacks")
        adm_instance = System.Activator.CreateInstance(t_adm)
        print(f"Instantiated BridgeAdmCallbacks: {adm_instance}")

        # REngineParamsの設定
        re_params = rapi.REngineParams()
        re_params.AppName = "RithmicBridge"
        re_params.AppVersion = "1.0.0"
        re_params.AdmCallbacks = adm_instance
        
        # ログファイル
        log_path = os.path.join(os.getcwd(), "rapi_test.log")
        with open(log_path, "w") as f: pass
        re_params.LogFilePath = log_path
        
        # 追加のパラメータ設定（bad input回避のため）
        # Rithmicのドキュメントがないので推測だが、接続先アドレス系が必要かも？
        # しかし通常は login() で指定するはず。
        # ここでは空文字などを試す
        re_params.DmnSrvrAddr = "ritm001.rithmic.com:10000" # 仮の値
        re_params.DomainName = "rithmic_paper_trading"      # 仮の値
        re_params.LicSrvrAddr = "ritm001.rithmic.com:56000" # 仮の値
        re_params.LocBrokAddr = "ritm001.rithmic.com:56000" # 仮の値
        re_params.LoggerAddr = "ritm001.rithmic.com:56000"  # 仮の値
        
        print(f"LogFilePath: {re_params.LogFilePath}")

        # Python関数の登録テスト
        def on_alert(info):
            print(f"[PYTHON] Alert received: {info.Message}")
        
        try:
            from System import Action
            # AlertInfo型を取得
            t_alert_info = assembly.GetType("com.omnesys.rapi.AlertInfo")
            if not t_alert_info:
                # rapiplusから直接とる
                import com.omnesys.rapi as rapi
                t_alert_info = rapi.AlertInfo
            
            # Action<AlertInfo> を作成
            action_type = Action[t_alert_info]
            adm_instance.OnAlert = action_type(on_alert)
            print("Linked Python function to C# delegate.")
        except Exception as e:
            print(f"Failed to link delegate: {e}")

        # REngineインスタンス化
        try:
            engine = rapi.REngine(re_params)
            print("SUCCESS: REngine instantiated!")
        except Exception as e:
            print(f"REngine instantiation failed: {e}")

    except Exception as e:
        print(f"General Error: {e}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    compile_and_test()
