using System;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using UnityEngine.Events;

public class FFI
{
#if UNITY_IOS || UNITY_TVOS
    public const string ImportName = "__Internal";
#else
    public const string ImportName = "rusty";
#endif
}

internal class StringHandle : SafeHandle
{
    [DllImport(FFI.ImportName)]
    private static extern void FreeString(IntPtr handle);

    public StringHandle() : base(IntPtr.Zero, true) { }

    public override bool IsInvalid
    {
        get { return false; }
    }

    public string AsString()
    {
        int len = 0;
        while (Marshal.ReadByte(handle, len) != 0) { ++len; }
        byte[] buffer = new byte[len];
        Marshal.Copy(handle, buffer, 0, buffer.Length);
        return Encoding.UTF8.GetString(buffer);
    }

    protected override bool ReleaseHandle()
    {
        FreeString(handle);
        return true;
    }
}

[System.Serializable]
public class StatusChangedEvent : UnityEvent<string> { }

public class Rusty : MonoBehaviour
{
    [DllImport(FFI.ImportName)]
    private static extern StringHandle DoSomeInterestingWork(int count, string content);

    public StatusChangedEvent OnStatusChanged;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public void SayHello()
    {
        var rng = new System.Random();
        OnStatusChanged.Invoke(DoSomeInterestingWork(rng.Next(1, 10), "Hello").AsString());
    }
}
