using System;
using System.Reflection;
using com.itac.mes.imsapi.client.dotnet;

internal static class Program
{
    private static int Fail(string text)
    {
        Console.Error.WriteLine("ABI FAIL: " + text);
        return 2;
    }

    private static int Main()
    {
        try
        {
            // This call is intentionally compiled against 10.0.0-3. The resulting EXE
            // must run unchanged after IMSApiDotNet.dll is replaced by either new target.
            IMSApiDotNet.setProperty("itac.appid", "LegacyBinarySmoke");

            IMSApiDotNet a = IMSApiDotNet.loadLibrary();
            IMSApiDotNet b = IMSApiDotNet.loadLibrary();
            if (a == null || b == null) return Fail("loadLibrary returned null");
            if (!object.ReferenceEquals(a, b)) return Fail("legacy singleton behavior changed");

            string version = null;
            int rc = a.imsapiGetLibraryVersion(ref version);
            if (rc != IMSApiDotNetConstants.RES_OK) return Fail("imsapiGetLibraryVersion return code " + rc);
            if (string.IsNullOrEmpty(version)) return Fail("empty library version");

            // Reflection checks the declaring type and static/instance metadata that caused
            // MissingMethodException in existing applications.
            MethodInfo setProperty = typeof(IMSApiDotNetBase).GetMethod(
                "setProperty",
                BindingFlags.Public | BindingFlags.Static,
                null,
                new[] { typeof(string), typeof(string) },
                null);
            if (setProperty == null) return Fail("IMSApiDotNetBase.setProperty(string,string) static missing");
            if (setProperty.ReturnType != typeof(void)) return Fail("setProperty return type changed");
            if (setProperty.DeclaringType != typeof(IMSApiDotNetBase)) return Fail("setProperty declaring type changed");

            MethodInfo loadLibrary = typeof(IMSApiDotNet).GetMethod(
                "loadLibrary",
                BindingFlags.Public | BindingFlags.Static,
                null,
                Type.EmptyTypes,
                null);
            if (loadLibrary == null || loadLibrary.ReturnType != typeof(IMSApiDotNet))
                return Fail("IMSApiDotNet.loadLibrary() signature changed");

            if (!typeof(IMSApiDotNetConstants).IsAssignableFrom(typeof(IMSApiDotNetBase)))
                return Fail("IMSApiDotNetBase no longer derives from IMSApiDotNetConstants");

            MethodInfo getError = typeof(IMSApiDotNetConstants).GetMethod(
                "getIMSApiDotNetErrorText",
                new[] { typeof(int) });
            if (getError == null || getError.ReturnType != typeof(string))
                return Fail("IMSApiDotNetConstants.getIMSApiDotNetErrorText(int) missing");

            Console.WriteLine("ABI OK");
            Console.WriteLine("Loaded: " + typeof(IMSApiDotNet).Assembly.FullName);
            Console.WriteLine("Path:   " + typeof(IMSApiDotNet).Assembly.Location);
            Console.WriteLine("API:    " + version);
            return 0;
        }
        catch (MissingMethodException ex)
        {
            return Fail(ex.ToString());
        }
        catch (TypeLoadException ex)
        {
            return Fail(ex.ToString());
        }
        catch (Exception ex)
        {
            return Fail(ex.ToString());
        }
    }
}
