// 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>
	/// <p>This type will be used to retrieve and manage the creation of the various calendar service types. </p> <p/> <p>General concepts: </p> <p>- Presents a set of API's that allow for the creation of a calendar service. </p> <p>- The types of calendar services offered will depend on the implementations that are built and packaged against these API's as plugins </p> <p>- The type of calendar service types defined may change as new implementations are added. </p> <p>- The service type will dicate how an application will construct the servce through this calendar service manager API </p> <p>=> A set of connection properties will be passed into the create service methods based on the service type. </p> <p>- The service manager will pass back a constructed calendar service type, which can then be used to connect to the service with and manage meeting setups and receive events for that service. </p> <p/> <p>Note that the availability of a service may come and go based on local applications or network events. </p>
	/// </summary>
	public class CalendarManager: IDisposable {
		private bool disposed = false; 
#if __IOS__
		const string importLib = "__Internal";
#else
		const string importLib = "libVidyoClient";
#endif
		private IntPtr objPtr; // opaque VidyoCalendarManager reference.
		private GCHandle objHandle; // weak VidyoCalendarManager reference.
		public IntPtr GetObjectPtr() {
			return objPtr;
		}
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoCalendarManagerConstructNative(IntPtr feedback);

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

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoCalendarManagerCreateCalendarInstanceNative(IntPtr calMgr, IntPtr feedback, IntPtr pluginServiceId, IntPtr calendarName, IntPtr createToken);

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

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

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

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoCalendarManagerGetCalendarRegisteredServicesGetsvcNamesArrayNative(IntPtr obj, ref int size);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoCalendarManagerGetCalendarRegisteredServicesFreesvcNamesArrayNative(IntPtr obj, int size);

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

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

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoCalendarManagerGetCalendarRegisteredServicesAsyncNative(IntPtr cm, OnGetServicesComplete onComplete);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoCalendarManagerRegisterCalendarServiceNative(IntPtr cm, IntPtr pluginServiceName, IntPtr dllName);

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

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

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnGetServicesComplete(IntPtr cm, IntPtr svcNames, CalendarManagerGetServicesResult result);
		private OnGetServicesComplete _mOnGetServicesComplete = OnGetServicesCompleteDelegate;
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoCalendarManagerOnGetServicesCompleteGetsvcNamesArrayNative(IntPtr obj, ref int size);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoCalendarManagerOnGetServicesCompleteFreesvcNamesArrayNative(IntPtr obj, int size);

		/// <summary>
		/// Result of getting the calendar services.
		/// </summary>
		public enum CalendarManagerGetServicesResult {
			/// <summary>Calendar services was got successfully.</summary>
			CalendarmanagergetservicesresultSUCCESS,
			/// <summary>Getting the calendar services failed some miscellaneous reason.</summary>
			CalendarmanagergetservicesresultMiscError
		}
		public interface IGetCalendarRegisteredServicesAsync{

			void OnGetServicesComplete(List<String> svcNames, CalendarManagerGetServicesResult result);
		}
		private IGetCalendarRegisteredServicesAsync _mIGetCalendarRegisteredServicesAsync;
		/// <summary>
		/// Constructor for Vidyo Calendar Service Manager
		/// </summary>
		/// <param name="calendarMgr"></param>
		/// <param name="feedback"></param>
		/// <param name="alloc"></param>
		public CalendarManager(CalendarManagerFeedback feedback) {

			objPtr = VidyoCalendarManagerConstructNative((feedback != null) ? feedback.GetObjectPtr():IntPtr.Zero);
			objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
			if (objPtr != IntPtr.Zero) {
				VidyoCalendarManagerSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		public CalendarManager(IntPtr from){
			objPtr = VidyoCalendarManagerConstructCopyNative(from);
			if (objPtr != IntPtr.Zero) {
				objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
				VidyoCalendarManagerSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		~CalendarManager(){
			Dispose(false);
		}
		public void Dispose(){
			Dispose(true);
			GC.SuppressFinalize(this);
		}

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

			disposed = true;
			if(objPtr != IntPtr.Zero) {
				VidyoCalendarManagerSetUserDataNative(objPtr, IntPtr.Zero);
				VidyoCalendarManagerDestructNative(objPtr);
				objPtr = IntPtr.Zero;
			}

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

		/// <summary>
		/// Creates a VidyoCalendar which is returned through VidyoCalendarManagerFeedbackCalendarCreated. Will be identifiable through the service ID and calendarName.
		/// </summary>
		/// <param name="calMgr"></param>
		/// <param name="feedback">Calendar feeback handle</param>
		/// <param name="pluginServiceId">The plugin service Id string that was used to register the plugin dll using VidyoCalendarManagerRegisterCalendarService</param>
		/// <param name="calendarName">Name of the calendar or calendar folder that will be used to operate against for the service. An empty string indicates that the default calendar should be used.</param>
		/// <param name="createToken"></param>
		public Boolean CreateCalendarInstance(CalendarFeedback feedback, String pluginServiceId, String calendarName, String createToken) {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nPluginServiceId = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(pluginServiceId ?? string.Empty);
			IntPtr nCalendarName = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(calendarName ?? string.Empty);
			IntPtr nCreateToken = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(createToken ?? string.Empty);
			Boolean ret = VidyoCalendarManagerCreateCalendarInstanceNative(objPtr, (feedback != null) ? feedback.GetObjectPtr():IntPtr.Zero, nPluginServiceId, nCalendarName, nCreateToken);
			Marshal.FreeHGlobal(nCreateToken);
			Marshal.FreeHGlobal(nCalendarName);
			Marshal.FreeHGlobal(nPluginServiceId);

			return ret;
		}
		/// <summary>
		/// Cleans up and removes the VidyoCalendar calendar instance passed in. NOTE.... IMPORTANT: This method must be called against any constructed instance of the cal endar instance before destructing the calendar manager. If the the instance is not destructed a memory leak will occur and-or side affects will appear from the underlying plugin not being destructed before a shutdown.
		/// </summary>
		/// <param name="calMgr"></param>
		/// <param name="cal">Calendar handle</param>
		public Boolean DestroyCalendarInstance(Calendar cal) {
			if (objPtr == IntPtr.Zero) { return default; }

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

			return ret;
		}
		/// <summary>
		/// Retrieves the list of calendar service strings that were successfully added to the calendar manager.
		/// </summary>
		/// <param name="cm">Instance of the calendar manager.</param>
		/// <param name="svcNames">Will be populated with the list of service name strings of the plug-in modules that were successfully added to the calendar manager.</param>
		public Boolean GetCalendarRegisteredServices(ref List<String> svcNames) {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nListSvcNames = VidyoCalendarManagerVectorLmiStringAllocateNative();

			Boolean ret = VidyoCalendarManagerGetCalendarRegisteredServicesNative(objPtr, nListSvcNames);

			List<String> csSvcNames = new List<String>();
			var nSvcNamesSize = 0;
			var nSvcNames = VidyoCalendarManagerGetCalendarRegisteredServicesGetsvcNamesArrayNative(nListSvcNames, ref nSvcNamesSize);
			var nSvcNamesIndex = 0;
			while (nSvcNamesIndex < nSvcNamesSize) {
				csSvcNames.Add((string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(Marshal.ReadIntPtr(nSvcNames + (nSvcNamesIndex * Marshal.SizeOf(nSvcNames)))));
				nSvcNamesIndex++;
			}

			svcNames = csSvcNames;
			VidyoCalendarManagerGetCalendarRegisteredServicesFreesvcNamesArrayNative(nSvcNames, nSvcNamesSize);
			VidyoCalendarManagerVectorLmiStringDeallocateNative(nListSvcNames);

			return ret;
		}
		/// <summary>
		/// Retrieves the list of calendar service strings that were successfully added to the calendar manager.
		/// </summary>
		/// <param name="cm">Instance of the calendar manager.</param>
		/// <param name="onComplete">The callback that is triggered when getting calendar service completes.</param>
		public Boolean GetCalendarRegisteredServicesAsync(IGetCalendarRegisteredServicesAsync _iIGetCalendarRegisteredServicesAsync) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIGetCalendarRegisteredServicesAsync = _iIGetCalendarRegisteredServicesAsync;

			Boolean ret = VidyoCalendarManagerGetCalendarRegisteredServicesAsyncNative(objPtr, _mOnGetServicesComplete);

			return ret;
		}
		/// <summary>
		/// Retreives the user data pointer that was previousely set by Calendaring VidyoCalendarManagerSetUserData.
		/// </summary>
		/// <param name="cm">Pointer to the VidyoCalendarManager object.</param>
		/// <param name="pluginServiceName">Service name string that will be used for to reference the service that will be provided by the dll being loaded. This name will be used as an argument for creating the calendar instance in VidyoCalendarManagerCreateCalendarInstance.</param>
		/// <param name="dllName">Full file name for calendar plugin dll that needs to be loaded for the pluginServiceName</param>
		public Boolean RegisterCalendarService(String pluginServiceName, String dllName) {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nPluginServiceName = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(pluginServiceName ?? string.Empty);
			IntPtr nDllName = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(dllName ?? string.Empty);
			Boolean ret = VidyoCalendarManagerRegisterCalendarServiceNative(objPtr, nPluginServiceName, nDllName);
			Marshal.FreeHGlobal(nDllName);
			Marshal.FreeHGlobal(nPluginServiceName);

			return ret;
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnGetServicesComplete))]
#endif
		private static void OnGetServicesCompleteDelegate(IntPtr cm, IntPtr svcNames, CalendarManagerGetServicesResult result){
			var csCmPtr = cm != IntPtr.Zero ? VidyoCalendarManagerGetUserDataNative(cm) : IntPtr.Zero;
			if(csCmPtr == IntPtr.Zero) return;
			var csCm = (CalendarManager)GCHandle.FromIntPtr(csCmPtr).Target;

			List<String> csSvcNames = new List<String>();
			var nSvcNamesSize = 0;
			var nSvcNames = VidyoCalendarManagerOnGetServicesCompleteGetsvcNamesArrayNative(svcNames, ref nSvcNamesSize);
			var nSvcNamesIndex = 0;
			while (nSvcNamesIndex < nSvcNamesSize) {
				csSvcNames.Add((string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(Marshal.ReadIntPtr(nSvcNames + (nSvcNamesIndex * Marshal.SizeOf(nSvcNames)))));
				nSvcNamesIndex++;
			}

			csCm?._mIGetCalendarRegisteredServicesAsync?.OnGetServicesComplete(csSvcNames, result);
			VidyoCalendarManagerOnGetServicesCompleteFreesvcNamesArrayNative(nSvcNames, nSvcNamesSize);
		}
	};
}
