using System;
using PPJ.Runtime;
using PPJ.Runtime.Sql;
using PPJ.Runtime.Windows;

// Small runtime checks for the documentation. No database or UI is opened.
public static class RuntimeConceptChecks
{
    public static void RunChecks()
    {
        SalNumber missing = SalNumber.Null;
        SalNumber zero = 0;
        Check(missing.IsNull && !zero.IsNull, "numeric null differs from zero");
        decimal? native = missing.IsNull ? (decimal?)null : missing.ToDecimal();
        Check(native == null, "nullable conversion preserves missing value");

        var names = new SalArray<SalString>();
        SetName(ref names.GetArray(10)[10]);
        Check((string)names[10] == "received", "receive updates the PPJ element");
        Check(names.GetArray().Length >= 11, "index 10 requires at least eleven slots");
        var bounded = new SalArray<SalString>("2:10");
        bounded[2] = "first";
        bounded[10] = "last";
        Check((string)bounded[2] == "first" && (string)bounded[10] == "last", "declared bounds");

        var locals = new object();
        var owner = new object();
        var previous = SqlContext.Current;
        using (var outer = new SqlContext(locals, owner))
        {
            Check(Object.ReferenceEquals(SqlContext.Current.Locals, locals), "locals argument is first");
            Check(Object.ReferenceEquals(SqlContext.Current.Container, owner), "container argument is second");
            try
            {
                using (new SqlContext(new object(), new object()))
                {
                    throw new InvalidOperationException("Test scope unwinding");
                }
            }
            catch (InvalidOperationException)
            {
                Check(Object.ReferenceEquals(SqlContext.Current, outer), "exception restores outer context");
            }
        }
        Check(Object.ReferenceEquals(SqlContext.Current, previous), "outer disposal restores previous context");

        var action = new WindowActionsEventArgs(IntPtr.Zero, Sys.SAM_Click, IntPtr.Zero, IntPtr.Zero);
        action.Handled = true;
        Check(!action.HasReturnValue, "Handled alone supplies no return");
        action.Return = 0;
        Check(action.Handled && action.HasReturnValue && action.Return == 0, "zero is an explicit return");
    }

    private static void SetName(ref SalString value) { value = "received"; }
    private static void Check(bool condition, string name)
    {
        if (!condition) throw new InvalidOperationException("Failed: " + name);
        Console.WriteLine("PASS: " + name);
    }
}
