///////////////////////////////////////////////////////////////////////////////
//
// (C) 2024 ICE TEA GROUP LLC - ALL RIGHTS RESERVED
//
// 
//
// ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS
// THE PROPERTY OF ICE TEA GROUP LLC AND ITS SUPPLIERS, IF ANY.
// THE INTELLECTUAL PROPERTY AND TECHNICAL CONCEPTS CONTAINED
// HEREIN ARE PROPRIETARY TO ICE TEA GROUP LLC AND ITS SUPPLIERS
// AND MAY BE COVERED BY U.S. AND FOREIGN PATENTS, PATENT IN PROCESS, AND
// ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW.
//
// DISSEMINATION OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL
// IS STRICTLY FORBIDDEN UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED
// FROM ICE TEA GROUP LLC.
//
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Drawing;
using System.Globalization;
using System.Threading.Tasks;
using Wisej.Ext.Tesseract;
using Wisej.Web;
using System.ComponentModel;

namespace Wisej.AI.Services
{
	/// <summary>
	/// Represents a default implementation of the <see cref="IOCRService"/> interface using
	/// Tesseract for Optical Character Recognition (OCR).
	/// </summary>
	[ApiCategory("Services/IOCRService")]
	public class DefaultOCRService : IOCRService
	{
		private Tesseract _tesseract;

		/// <summary>
		/// Initializes a new instance of the <see cref="DefaultOCRService"/> class.
		/// </summary>
		public DefaultOCRService()
		{
			_tesseract = new Tesseract
			{
				ShowWords = false
			};
		}

		/// <summary>
		/// Gets or sets the language used for OCR processing.
		/// </summary>
		/// <remarks>
		/// The language should be specified as a <see cref="CultureInfo"/> object. 
		/// If the language is not set, the default language used is English ("eng").
		/// </remarks>
		public CultureInfo Language { get; set; }

		/// <summary>
		/// Scans an image and performs OCR to extract text from it.
		/// </summary>
		/// <param name="image">The image to be scanned. It should be a valid <see cref="Image"/> object. Defaults to null.</param>
		/// <returns>A <see cref="Task"/> representing the asynchronous operation, with the recognized text as the result.</returns>
		/// <exception cref="ArgumentNullException">Thrown if the <paramref name="image"/> parameter is null.</exception>
		/// <remarks>
		/// <para>
		/// This method performs OCR on the provided image using the specified language set in the <see cref="Language"/> property.
		/// If the language is not set, English is used by default.
		/// </para>
		/// <para>
		/// Example usage:
		/// <code><![CDATA[
		/// DefaultOCRService ocrService = new DefaultOCRService
		/// {
		///     Language = new CultureInfo("eng")
		/// };
		/// Image image = Image.FromFile("sample.png");
		/// string text = await ocrService.ScanImageAsync(image);
		/// Console.WriteLine(text);
		/// ]]></code>
		/// </para>
		/// </remarks>
		public async Task<string> ScanImageAsync(Image image)
		{
			if (image == null)
				throw new ArgumentNullException(nameof(image), "The image cannot be null.");

			_tesseract.Language = this.Language?.ThreeLetterISOLanguageName.ToLowerInvariant() ?? "eng";
			var result = _tesseract.ScanImageAsync(image);
			Application.Update(Application.Current);
			return (await result).Text ?? "";
		}

		/// <summary>
		/// Asynchronously scans an image from a URL and returns the recognized text.
		/// </summary>
		/// <param name="imageUrl">The URL of the image to be scanned for text recognition. This parameter is not optional.</param>
		/// <returns>A task representing the asynchronous operation, with the recognized text as the result.</returns>
		/// <exception cref="ArgumentException">Thrown when <paramref name="imageUrl"/> is null or empty.</exception>
		/// <remarks>
		/// <para>
		/// This method retrieves an image from the provided URL and utilizes the Tesseract OCR engine to recognize text.
		/// The language used for OCR is specified by the <see cref="Language"/> property.
		/// </para>
		/// <para>
		/// Example usage:
		/// <code><![CDATA[
		/// var ocrService = new DefaultOCRService();
		/// ocrService.Language = new CultureInfo("eng");
		/// string recognizedText = await ocrService.ScanImageAsync("http://example.com/image.jpg");
		/// Console.WriteLine(recognizedText);
		/// ]]></code>
		/// </para>
		/// </remarks>
		public async Task<string> ScanImageAsync(string imageUrl)
		{
			if (string.IsNullOrEmpty(imageUrl))
				throw new ArgumentException("The image path cannot be null or empty.", nameof(imageUrl));

			_tesseract.Language = this.Language?.ThreeLetterISOLanguageName.ToLowerInvariant() ?? "eng";
			var result = await _tesseract.ScanImageAsync(imageUrl);
			return result?.Text ?? string.Empty;
		}

		/// <summary>
		/// Releases all resources used by the <see cref="DefaultOCRService"/>.
		/// </summary>
		/// <remarks>
		/// This method should be called when the service is no longer needed to free up resources.
		/// </remarks>
		public void Dispose()
		{
			_tesseract.Dispose();
		}
	}
}
