using System;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;

namespace Vanara.PInvoke
{
	public static partial class Shell32
	{
		/// <summary>Exposes resource enumeration methods.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ienumresources
		[PInvokeData("shobjidl_core.h", MSDNShortId = "NN:shobjidl_core.IEnumResources")]
		[ComImport, Guid("2dd81fe3-a83c-4da9-a330-47249d345ba1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IEnumResources
		{
			/// <summary>Gets the next SHELL_ITEM_RESOURCE structure.</summary>
			/// <param name="celt">
			/// <para>Type: <c>ULONG</c></para>
			/// <para>The number of resources requested. Currently, must be 1.</para>
			/// </param>
			/// <param name="psir">
			/// <para>Type: <c>SHELL_ITEM_RESOURCE*</c></para>
			/// <para>Receives a pointer to a SHELL_ITEM_RESOURCE structure.</para>
			/// </param>
			/// <param name="pceltFetched">
			/// <para>Type: <c>ULONG*</c></para>
			/// <para>A pointer to the number of resources retrieved. Currently, not used.</para>
			/// </param>
			/// <returns>
			/// <para>Type: <c>HRESULT</c></para>
			/// <para>If this method succeeds, it returns <c>S_OK</c>. Otherwise, it returns an <c>HRESULT</c> error code.</para>
			/// </returns>
			// https://docs.microsoft.com/fr-fr/windows/win32/api/shobjidl_core/nf-shobjidl_core-ienumresources-next HRESULT Next( ULONG
			// celt, SHELL_ITEM_RESOURCE *psir, ULONG *pceltFetched );
			[PreserveSig]
			HRESULT Next(uint celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] SHELL_ITEM_RESOURCE[] psir, out uint pceltFetched);

			/// <summary>Skips a specified number of resources.</summary>
			/// <param name="celt">
			/// <para>Type: <c>ULONG</c></para>
			/// <para>The number of resources to skip.</para>
			/// </param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ienumresources-skip HRESULT Skip( ULONG
			// celt );
			void Skip(uint celt);

			/// <summary>Resets the enumeration index to 0.</summary>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ienumresources-reset HRESULT Reset();
			void Reset();

			/// <summary>Clones a resource enumerator.</summary>
			/// <returns>
			/// <para>Type: <c>IEnumResources**</c></para>
			/// <para>Contains the address of an IEnumResources interface pointer.</para>
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ienumresources-clone HRESULT Clone(
			// IEnumResources **ppenumr );
			IEnumResources Clone();
		}

		/// <summary>Exposes methods to manipulate and query Shell item resources.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ishellitemresources
		[PInvokeData("shobjidl_core.h", MSDNShortId = "NN:shobjidl_core.IShellItemResources")]
		[ComImport, Guid("ff5693be-2ce0-4d48-b5c5-40817d1acdb9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IShellItemResources
		{
			/// <summary>Gets resource attributes.</summary>
			/// <returns>
			/// <para>Type: <c>DWORD*</c></para>
			/// <para>A pointer to resource attributes. The following are attribute values.</para>
			/// <para>FILE_ATTRIBUTE_READONLY</para>
			/// <para>Value is 0x00000001.</para>
			/// <para>FILE_ATTRIBUTE_HIDDEN</para>
			/// <para>Value is 0x00000002.</para>
			/// <para>FILE_ATTRIBUTE_SYSTEM</para>
			/// <para>Value is 0x00000004.</para>
			/// <para>FILE_ATTRIBUTE_DIRECTORY</para>
			/// <para>Value is 0x00000010.</para>
			/// <para>FILE_ATTRIBUTE_ARCHIVE</para>
			/// <para>Value is 0x00000020.</para>
			/// <para>FILE_ATTRIBUTE_ENCRYPTED</para>
			/// <para>Value is 0x00000040.</para>
			/// <para>FILE_ATTRIBUTE_NORMAL</para>
			/// <para>Value is 0x00000080.</para>
			/// <para>FILE_ATTRIBUTE_TEMPORARY</para>
			/// <para>Value is 0x00000100.</para>
			/// <para>FILE_ATTRIBUTE_SPARSE_FILE</para>
			/// <para>Value is 0x00000200.</para>
			/// <para>FILE_ATTRIBUTE_REPARSE_POINT</para>
			/// <para>Value is 0x00000400.</para>
			/// <para>FILE_ATTRIBUTE_COMPRESSED</para>
			/// <para>Value is 0x00000800.</para>
			/// <para>FILE_ATTRIBUTE_OFFLINE</para>
			/// <para>Value is 0x00001000.</para>
			/// <para>FILE_ATTRIBUTE_CONTENT_INDEXED</para>
			/// <para>Value is 0x00002000.</para>
			/// <para>FILE_ATTRIBUTE_VALID_FLAGS</para>
			/// <para>Value is 0x00001ff7.</para>
			/// <para>FILE_ATTRIBUTE_VALID_SET_FLAGS</para>
			/// <para>Value is 0x000011a7.</para>
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-getattributes HRESULT
			// GetAttributes( DWORD *pdwAttributes );
			FileFlagsAndAttributes GetAttributes();

			/// <summary>Gets the source size.</summary>
			/// <returns>
			/// <para>Type: <c>ULONGLONG*</c></para>
			/// <para>A pointer to the source size.</para>
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-getsize HRESULT
			// GetSize( ULONGLONG *pullSize );
			ulong GetSize();

			/// <summary>Gets file times.</summary>
			/// <param name="pftCreation">The filetime.</param>
			/// <param name="pftWrite">The filetime.</param>
			/// <param name="pftAccess">The filetime.</param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-gettimes HRESULT
			// GetTimes( FILETIME *pftCreation, FILETIME *pftWrite, FILETIME *pftAccess );
			void GetTimes(out FILETIME pftCreation, out FILETIME pftWrite, out FILETIME pftAccess);

			/// <summary>Sets file times.</summary>
			/// <param name="pftCreation">
			/// <para>Type: <c>const FILETIME*</c></para>
			/// <para>A pointer to a creation date and time as a FILETIME structure.</para>
			/// </param>
			/// <param name="pftWrite">
			/// <para>Type: <c>const FILETIME*</c></para>
			/// <para>A pointer to a write date and time as a FILETIME structure.</para>
			/// </param>
			/// <param name="pftAccess">
			/// <para>Type: <c>const FILETIME*</c></para>
			/// <para>A pointer to an access date and time as a FILETIME structure.</para>
			/// </param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-settimes HRESULT
			// SetTimes( const FILETIME *pftCreation, const FILETIME *pftWrite, const FILETIME *pftAccess );
			void SetTimes([In, Optional] IntPtr pftCreation, [In, Optional] IntPtr pftWrite, [In, Optional] IntPtr pftAccess);

			/// <summary>Gets a resource description.</summary>
			/// <param name="pcsir">
			/// <para>Type: <c>const SHELL_ITEM_RESOURCE*</c></para>
			/// <para>A pointer to a SHELL_ITEM_RESOURCE resource.</para>
			/// </param>
			/// <returns>
			/// <para>Type: <c>LPWSTR*</c></para>
			/// <para>A pointer to a resource description as a Unicode string.</para>
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-getresourcedescription
			// HRESULT GetResourceDescription( const SHELL_ITEM_RESOURCE *pcsir, LPWSTR *ppszDescription );
			[return: MarshalAs(UnmanagedType.LPWStr)]
			string GetResourceDescription(in SHELL_ITEM_RESOURCE pcsir);

			/// <summary>Gets a resource enumerator object.</summary>
			/// <returns>
			/// <para>Type: <c>IEnumResources**</c></para>
			/// <para>The address of an IEnumResources interface pointer.</para>
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-enumresources HRESULT
			// EnumResources( IEnumResources **ppenumr );
			IEnumResources EnumResources();

			/// <summary>Retrieves whether an item supports a specified resource.</summary>
			/// <param name="pcsir">The shell item resource.</param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-supportsresource
			// HRESULT SupportsResource( const SHELL_ITEM_RESOURCE *pcsir );
			void SupportsResource(in SHELL_ITEM_RESOURCE pcsir);

			/// <summary>Opens a specified resource.</summary>
			/// <param name="pcsir">
			/// <para>Type: <c>const SHELL_ITEM_RESOURCE*</c></para>
			/// <para>A pointer to a SHELL_ITEM_RESOURCE resource.</para>
			/// </param>
			/// <param name="riid">
			/// <para>Type: <c>REFIID</c></para>
			/// <para>A reference to a desired IID.</para>
			/// </param>
			/// <param name="ppv">
			/// <para>Type: <c>void**</c></para>
			/// <para>The address of a pointer to a resource.</para>
			/// </param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-openresource HRESULT
			// OpenResource( const SHELL_ITEM_RESOURCE *pcsir, REFIID riid, void **ppv );
			void OpenResource(in SHELL_ITEM_RESOURCE pcsir, in Guid riid, [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1)] out object ppv);

			/// <summary>Creates a specified resource.</summary>
			/// <param name="pcsir">
			/// <para>Type: <c>const SHELL_ITEM_RESOURCE*</c></para>
			/// <para>A pointer to an SHELL_ITEM_RESOURCE resource.</para>
			/// </param>
			/// <param name="riid">
			/// <para>Type: <c>REFIID</c></para>
			/// <para>A reference to a desired IID.</para>
			/// </param>
			/// <param name="ppv">
			/// <para>Type: <c>void**</c></para>
			/// <para>The address of a pointer to the resource.</para>
			/// </param>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-createresource HRESULT
			// CreateResource( const SHELL_ITEM_RESOURCE *pcsir, REFIID riid, void **ppv );
			void CreateResource(in SHELL_ITEM_RESOURCE pcsir, in Guid riid, [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1)] out object ppv);

			/// <summary>Marks for delete.</summary>
			// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemresources-markfordelete HRESULT MarkForDelete();
			void MarkForDelete();
		}

		/// <summary>Sets file times.</summary>
		/// <param name="psir">The IShellItemResources instance.</param>
		/// <param name="ftCreation">An optional creation date and time.</param>
		/// <param name="ftWrite">An optional write date and time.</param>
		/// <param name="ftAccess">An optional access date and time.</param>
		public static void SetTimes(this IShellItemResources psir, DateTime? ftCreation, DateTime? ftWrite, DateTime? ftAccess) =>
			psir.SetTimes((SafeCoTaskMemStruct<FILETIME>)ftCreation?.ToFileTimeStruct(), (SafeCoTaskMemStruct<FILETIME>)ftWrite?.ToFileTimeStruct(), (SafeCoTaskMemStruct<FILETIME>)ftAccess?.ToFileTimeStruct());

		/// <summary>Defines Shell item resource.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/ns-shobjidl_core-shell_item_resource typedef struct
		// SHELL_ITEM_RESOURCE { GUID guidType; WCHAR szName[260]; } SHELL_ITEM_RESOURCE;
		[PInvokeData("shobjidl_core.h", MSDNShortId = "NS:shobjidl_core.SHELL_ITEM_RESOURCE")]
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		public struct SHELL_ITEM_RESOURCE
		{
			/// <summary>
			/// <para>Type: <c>GUID</c></para>
			/// <para>The <c>GUID</c> that identifies the item.</para>
			/// </summary>
			public Guid guidType;

			/// <summary>
			/// <para>Type: <c>WCHAR[MAX_PATH]</c></para>
			/// <para>The item name. A null-terminated Unicode buffer of size MAX_LENGTH characters.</para>
			/// </summary>
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
			public string szName;
		}
	}
}