/*
 * Copyright (c)2009-2025 DemiVision, LLC. All Rights Reserved. The information
 * herein is the CONFIDENTIAL and PROPRIETARY information of DemiVision, LLC.
 */

using System.Text.Json;
using System.Reflection;

using DXLib.Log;

namespace DXLib.Utils;

/*
 * Provides utility methods for dealing with local resources as well as dynamic class instantiation.
 */ 
public static class DXResource
{
	/* Properties */

	// Platform specific assembly
	public static Assembly Assembly { get; private set; }

	// Path to Resource directory
	public static string Path { get; private set; }

	/* Fields */
	
	// Reusable JSON config
	private static JsonSerializerOptions jsonOptions;
	
	/* Methods */

	// Initializes resource path for current platform specific assembly
	public static void Init( Type type )
	{
		// Cache assembly info
		Assembly = type.GetTypeInfo().Assembly;
		string assemblyName = Assembly.GetName().Name;
		
		if ( assemblyName != null )
		{
			string platform = assemblyName.Replace( "Android", "Droid" );

			Path = $"{platform}.Resources";
		}
		
		// Cache JSON options
		jsonOptions = new JsonSerializerOptions
		{
			PropertyNameCaseInsensitive = true
		};
	}

	// Dynamically instantiates class from specified name
	public static object CreateInstance( string className )
	{
		Assembly assembly = Assembly.GetExecutingAssembly();
		var type = assembly.GetTypes().First( t => t.Name == className );

		return Activator.CreateInstance( type );
	}

	// Opens input resource stream to specified local file
	public static async Task<Stream> OpenFile( string filename )
	{
		try
		{
			return await FileSystem.Current.OpenAppPackageFileAsync( filename );
		}
		catch ( Exception ex )
		{
			DXLog.Exception( "resource.openfile", ex );
			return null;
		}
	}

	// Reads and returns entire contents of specified local text file
	public static async Task<string> ReadFile( string filename )
	{
		// Open local stream
		await using Stream stream = await OpenFile( filename );

		// Read entire file as text
		using StreamReader reader = new( stream );
		string data = await reader.ReadToEndAsync();

		return data;
	}

	// Reads and returns entire contents of specified local binary file
	public static async Task<byte[]> ReadFileBytes( string filename )
	{
		// Open local stream
		await using Stream stream = await OpenFile( filename );

		int len = (int)stream.Length;

		// Allocate buffer
		byte[] buffer = new byte[ len ];

		// Read all contents into buffer
		int count = await stream.ReadAsync( buffer.AsMemory( 0, len ) );

		DXLog.Debug( "ReadFileBytes:{0}", count );
		
		return buffer;
	}
	
	// Reads specified file and deserializes into JSON for generic type
	public static async Task<T> ReadJson<T>( string filename )
	{
		// Read file
		string jsonFile = await ReadFile( filename );
		
		// Deserialize
		return JsonSerializer.Deserialize<T>( jsonFile, jsonOptions );
	}
	
	// Reads ImageSource from specified resource file
	public static ImageSource ReadImageSource( string resource )
	{
		return ImageSource.FromResource( $"{Path}.Images.{resource}", Assembly );
	}
}

//
