// 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>
	/// A wrapper for Vidyo gateways.
	/// </summary>
	public class Gateway: IDisposable {
		private bool disposed = false; 
#if __IOS__
		const string importLib = "__Internal";
#else
		const string importLib = "libVidyoClient";
#endif
		private IntPtr objPtr; // opaque VidyoGateway reference.
		private GCHandle objHandle; // weak VidyoGateway reference.
		public IntPtr GetObjectPtr() {
			return objPtr;
		}
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoGatewayConnectNative(IntPtr gateway, IntPtr host, IntPtr token, IntPtr displayName, IntPtr resourceId, OnSuccess onSuccess, OnFailure onFailure, OnDisconnected onDisconnected);

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

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

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

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

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

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnDisconnected(IntPtr gateway, GatewayDisconnectReason reason);
		private OnDisconnected _mOnDisconnected = OnDisconnectedDelegate;
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnFailure(IntPtr gateway, GatewayFailReason reason);
		private OnFailure _mOnFailure = OnFailureDelegate;
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnSuccess(IntPtr gateway);
		private OnSuccess _mOnSuccess = OnSuccessDelegate;
		/// <summary>
		/// Reasons why an established connection was disconnected.
		/// </summary>
		public enum GatewayDisconnectReason {
			/// <summary>The user disconnected gracefully.</summary>
			GatewaydisconnectreasonDisconnected,
			/// <summary>The transport connection was lost.</summary>
			GatewaydisconnectreasonConnectionLost,
			/// <summary>The signaling connection timed-out.</summary>
			GatewaydisconnectreasonConnectionTimeout,
			/// <summary>The service did not respond in a reasonable amount of time to a request by the user.</summary>
			GatewaydisconnectreasonNoResponse,
			/// <summary>The service closed the connection or otherwise terminated the login session.</summary>
			GatewaydisconnectreasonTerminated,
			/// <summary>A miscellaneous problem occurred with this client library.</summary>
			GatewaydisconnectreasonMiscLocalError,
			/// <summary>A miscellaneous problem occurred with the conferencing service.</summary>
			GatewaydisconnectreasonMiscRemoteError,
			/// <summary>The connection was closed for some other miscellaneous reason.</summary>
			GatewaydisconnectreasonMiscError
		}
		/// <summary>
		/// Reasons why a connection attempt failed.
		/// </summary>
		public enum GatewayFailReason {
			/// <summary>The destination could not be reached.</summary>
			GatewayfailreasonConnectionFailed,
			/// <summary>The transport connection was lost prior to completing the login procedure.</summary>
			GatewayfailreasonConnectionLost,
			/// <summary>The signaling connection timed-out prior to completing the login procedure.</summary>
			GatewayfailreasonConnectionTimeout,
			/// <summary>The service was successfully contacted, but the service ignored the user's request to log in or it did not answer in a reasonable amount of time.</summary>
			GatewayfailreasonNoResponse,
			/// <summary>The service was successfully contacted, but the service closed the connection or it refused to continue processing the login request.</summary>
			GatewayfailreasonTerminated,
			/// <summary>The token that was provided is unknown to the service or unauthorized to log in.</summary>
			GatewayfailreasonInvalidToken,
			/// <summary>The server was unable to create the resource.</summary>
			GatewayfailreasonUnableToCreateResource,
			/// <summary>The server did not respond in a reasonable amount of time to the request to connect to the resource.</summary>
			GatewayfailreasonNoResponseFromResource,
			/// <summary>The resource ID was invalid.</summary>
			GatewayfailreasonInvalidResourceId,
			/// <summary>The resource is at full capacity, and it cannot accept additional members.</summary>
			GatewayfailreasonResourceFull,
			/// <summary>The resource allows only certain users to enter, and the current user is not one of them.</summary>
			GatewayfailreasonNotMember,
			/// <summary>The user has been banned from entering the resource.</summary>
			GatewayfailreasonBanned,
			/// <summary>The client could not enable media.</summary>
			GatewayfailreasonMediaNotEnabled,
			/// <summary>An established media connection failed.</summary>
			GatewayfailreasonMediaFailed,
			/// <summary>The server rejected the user's request to enter the resource, due to a miscellaneous problem with the request.</summary>
			GatewayfailreasonMiscLocalError,
			/// <summary>The server rejected the user's request to enter the resource, due to a miscellaneous problem of its own.</summary>
			GatewayfailreasonMiscRemoteError,
			/// <summary>The login failed for some other miscellaneous reason.</summary>
			GatewayfailreasonMiscError
		}
		/// <summary>
		/// States of the VidyoGateway.
		/// </summary>
		public enum GatewayState {
			/// <summary>Ready to connect.</summary>
			GatewaystateIdle,
			/// <summary>Establishing a connection to the server.</summary>
			GatewaystateEstablishingConnection,
			/// <summary>Finding a resource.</summary>
			GatewaystateFindingResource,
			/// <summary>Connecting to a resource.</summary>
			GatewaystateConnectingToResource,
			/// <summary>Enabling media.</summary>
			GatewaystateEnablingMedia,
			/// <summary>Successfully connected.</summary>
			GatewaystateConnected
		}
		public interface IConnect{

			void OnSuccess();
			void OnFailure(GatewayFailReason reason);
			void OnDisconnected(GatewayDisconnectReason reason);
		}
		private IConnect _mIConnect;
		public Gateway(IntPtr other){
			objPtr = VidyoGatewayConstructCopyNative(other);
			if (objPtr != IntPtr.Zero) {
				objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
				VidyoGatewaySetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		~Gateway(){
			Dispose(false);
		}
		public void Dispose(){
			Dispose(true);
			GC.SuppressFinalize(this);
		}

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

			disposed = true;
			if(objPtr != IntPtr.Zero) {
				VidyoGatewaySetUserDataNative(objPtr, IntPtr.Zero);
				VidyoGatewayDestructNative(objPtr);
				objPtr = IntPtr.Zero;
			}

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

		/// <summary>
		/// Connects to a gateway to a live conference with the specified resourceId.
		/// </summary>
		/// <param name="gateway">The VidyoGateway object.</param>
		/// <param name="host">Host to which the connection will be made.</param>
		/// <param name="token">Token generated by the backend that contains the user ID and other metadata that will be used for authentication.</param>
		/// <param name="displayName">A display name that will be used in the UI.</param>
		/// <param name="resourceId">An alphanumeric string. This resourceId does does not need to be pre-provisioned but in order to create a connection between multiple participants, the same resource ID has to be specified.</param>
		/// <param name="onSuccess">Callback that is triggered when the connection is successfully established.</param>
		/// <param name="onFailure">Callback that is triggered when the connection establishemnt failed.</param>
		/// <param name="onDisconnected">Callback that is triggered when an established connection is disconnected.</param>
		public Boolean Connect(String host, String token, String displayName, String resourceId, IConnect _iIConnect) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIConnect = _iIConnect;

			IntPtr nHost = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(host ?? string.Empty);
			IntPtr nToken = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(token ?? string.Empty);
			IntPtr nDisplayName = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(displayName ?? string.Empty);
			IntPtr nResourceId = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(resourceId ?? string.Empty);
			Boolean ret = VidyoGatewayConnectNative(objPtr, nHost, nToken, nDisplayName, nResourceId, _mOnSuccess, _mOnFailure, _mOnDisconnected);
			Marshal.FreeHGlobal(nResourceId);
			Marshal.FreeHGlobal(nDisplayName);
			Marshal.FreeHGlobal(nToken);
			Marshal.FreeHGlobal(nHost);

			return ret;
		}
		/// <summary>
		/// Disconnects a live gateway call.
		/// </summary>
		/// <param name="gateway">The VidyoGateway object.</param>
		public void Disconnect() {
			if (objPtr == IntPtr.Zero) { return; }

			VidyoGatewayDisconnectNative(objPtr);
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnDisconnected))]
#endif
		private static void OnDisconnectedDelegate(IntPtr gateway, GatewayDisconnectReason reason){
			var csGatewayPtr = gateway != IntPtr.Zero ? VidyoGatewayGetUserDataNative(gateway) : IntPtr.Zero;
			if(csGatewayPtr == IntPtr.Zero) return;
			var csGateway = (Gateway)GCHandle.FromIntPtr(csGatewayPtr).Target;

			csGateway?._mIConnect?.OnDisconnected(reason);
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnFailure))]
#endif
		private static void OnFailureDelegate(IntPtr gateway, GatewayFailReason reason){
			var csGatewayPtr = gateway != IntPtr.Zero ? VidyoGatewayGetUserDataNative(gateway) : IntPtr.Zero;
			if(csGatewayPtr == IntPtr.Zero) return;
			var csGateway = (Gateway)GCHandle.FromIntPtr(csGatewayPtr).Target;

			csGateway?._mIConnect?.OnFailure(reason);
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnSuccess))]
#endif
		private static void OnSuccessDelegate(IntPtr gateway){
			var csGatewayPtr = gateway != IntPtr.Zero ? VidyoGatewayGetUserDataNative(gateway) : IntPtr.Zero;
			if(csGatewayPtr == IntPtr.Zero) return;
			var csGateway = (Gateway)GCHandle.FromIntPtr(csGatewayPtr).Target;

			csGateway?._mIConnect?.OnSuccess();
		}
	};
}
