// DO NOT EDIT! This is an autogenerated file. All changes will be
// overwritten!

//	Copyright (c) 2023 Vidyo, Inc. All rights reserved.


using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace VidyoClient
{
	/// <summary>
	/// This object represents a window share which belongs to the remote participant.
	/// </summary>
	public class RemoteWindowShare: IDisposable {
		private bool disposed = false; 
#if __IOS__
		const string importLib = "__Internal";
#else
		const string importLib = "libVidyoClient";
#endif
		private IntPtr objPtr; // opaque VidyoRemoteWindowShare reference.
		private GCHandle objHandle; // weak VidyoRemoteWindowShare reference.
		private List<WeakReference> objects = new List<WeakReference>();

		private void DisposeWeakReferenceObjects() {
			foreach(var item in objects) {
				if (item == null || !item.IsAlive || item.Target == null) { continue; }
				switch (item.Target.GetType().Name) {
					case "Participant": ((Participant)item.Target).Dispose(false); break;
				}
			}
			objects.Clear();
		}
		public IntPtr GetObjectPtr() {
			return objPtr;
		}
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern ulong VidyoRemoteWindowShareAddToLocalRendererNative(IntPtr w, IntPtr renderer);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteWindowShareConstructCopyNative(IntPtr other);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern void VidyoRemoteWindowShareDestructNative(IntPtr obj);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteWindowShareGetIdNative(IntPtr w);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteWindowShareGetNameNative(IntPtr w);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteWindowShareRegisterFrameEventListenerNative(IntPtr w, OnRemoteWindowShareFrame onFrame);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteWindowShareRemoveFromLocalRendererNative(IntPtr w, IntPtr renderer);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteWindowShareSetPositionInLocalRendererNative(IntPtr w, IntPtr localRenderer, int x, int y, uint width, uint height, ulong frameInterval);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteWindowShareUnregisterFrameEventListenerNative(IntPtr w);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		public static extern IntPtr VidyoRemoteWindowShareGetUserDataNative(IntPtr obj);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		public static extern void VidyoRemoteWindowShareSetUserDataNative(IntPtr obj, IntPtr userData);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnRemoteWindowShareFrame(IntPtr w, IntPtr participant, IntPtr videoFrame);
		private OnRemoteWindowShareFrame _mOnRemoteWindowShareFrame = OnRemoteWindowShareFrameDelegate;
		public interface IRegisterFrameEventListener{

			void OnRemoteWindowShareFrame(Participant participant, VideoFrame videoFrame);
		}
		private IRegisterFrameEventListener _mIRegisterFrameEventListener;
		public RemoteWindowShare(IntPtr other){
			objPtr = VidyoRemoteWindowShareConstructCopyNative(other);
			if (objPtr != IntPtr.Zero) {
				objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
				VidyoRemoteWindowShareSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		~RemoteWindowShare(){
			Dispose(false);
		}
		public void Dispose(){
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		public void Dispose(bool disposing){
			if(disposed) return;

			disposed = true;
			DisposeWeakReferenceObjects();
			if(objPtr != IntPtr.Zero) {
				VidyoRemoteWindowShareSetUserDataNative(objPtr, IntPtr.Zero);
				VidyoRemoteWindowShareDestructNative(objPtr);
				objPtr = IntPtr.Zero;
			}

			if(objHandle.IsAllocated) objHandle.Free();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		/// <param name="renderer"></param>
		public ulong AddToLocalRenderer(LocalRenderer renderer) {
			if (objPtr == IntPtr.Zero) { return default; }

			ulong ret = VidyoRemoteWindowShareAddToLocalRendererNative(objPtr, (renderer != null) ? renderer.GetObjectPtr():IntPtr.Zero);

			return ret;
		}
		/// <summary>
		/// Gets the unique ID of the window share.
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		public String GetId() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoRemoteWindowShareGetIdNative(objPtr);

			return (string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(ret);
		}
		/// <summary>
		/// Gets the name of the window share.
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		public String GetName() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoRemoteWindowShareGetNameNative(objPtr);

			return (string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(ret);
		}
		/// <summary>
		/// Registers to get notified about new remote window share frame.
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		/// <param name="onFrame">Callback that is triggered each time when we get a remote window share frame.</param>
		public Boolean RegisterFrameEventListener(IRegisterFrameEventListener _iIRegisterFrameEventListener) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIRegisterFrameEventListener = _iIRegisterFrameEventListener;

			Boolean ret = VidyoRemoteWindowShareRegisterFrameEventListenerNative(objPtr, _mOnRemoteWindowShareFrame);

			return ret;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		/// <param name="renderer"></param>
		public Boolean RemoveFromLocalRenderer(LocalRenderer renderer) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteWindowShareRemoveFromLocalRendererNative(objPtr, (renderer != null) ? renderer.GetObjectPtr():IntPtr.Zero);

			return ret;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		/// <param name="localRenderer"></param>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <param name="width"></param>
		/// <param name="height"></param>
		/// <param name="frameInterval"></param>
		public Boolean SetPositionInLocalRenderer(LocalRenderer localRenderer, int x, int y, uint width, uint height, ulong frameInterval) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteWindowShareSetPositionInLocalRendererNative(objPtr, (localRenderer != null) ? localRenderer.GetObjectPtr():IntPtr.Zero, x, y, width, height, frameInterval);

			return ret;
		}
		/// <summary>
		/// Unregisters remote window share frame notifications.
		/// </summary>
		/// <param name="w">The VidyoRemoteWindowShare object.</param>
		public Boolean UnregisterFrameEventListener() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteWindowShareUnregisterFrameEventListenerNative(objPtr);

			return ret;
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnRemoteWindowShareFrame))]
#endif
		private static void OnRemoteWindowShareFrameDelegate(IntPtr w, IntPtr participant, IntPtr videoFrame){
			var csWPtr = w != IntPtr.Zero ? VidyoRemoteWindowShareGetUserDataNative(w) : IntPtr.Zero;
			if(csWPtr == IntPtr.Zero) return;
			var csW = (RemoteWindowShare)GCHandle.FromIntPtr(csWPtr).Target;

			Participant csParticipant = null;
			if(participant != IntPtr.Zero) {
				var csParticipantPtr = Participant.VidyoParticipantGetUserDataNative(participant);
				if (csParticipantPtr == IntPtr.Zero) {
					csParticipant = new Participant(participant);
					if (csParticipant != null) {
						csW?.objects?.Add(new WeakReference(csParticipant));
					}
				} else {
					csParticipant = (Participant)GCHandle.FromIntPtr(csParticipantPtr).Target;
				}
			}

			VideoFrame csVideoFrame = null;
			if(videoFrame != IntPtr.Zero) {
				var csVideoFramePtr = VideoFrame.VidyoVideoFrameGetUserDataNative(videoFrame);
				csVideoFrame = csVideoFramePtr == IntPtr.Zero ? new VideoFrame(videoFrame) : (VideoFrame)GCHandle.FromIntPtr(csVideoFramePtr).Target;
			}

			csW?._mIRegisterFrameEventListener?.OnRemoteWindowShareFrame(csParticipant, csVideoFrame);
		}
	};
}
