using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;

namespace ANSCENTER
{
    public class ANSDLDOTNET
    {
        // Import the CreateANSODHandle_CS function
        [DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "CreateANSODHandle_CS", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern IntPtr CreateANSODHandle_CS(ref IntPtr handle,
                                                         string licenseKey,
                                                         string modelFilePath,
                                                         string modelFileZipPassword,
                                                         float modelThreshold,
                                                         float modelConfThreshold,
                                                         float modelNMSThreshold,
                                                         int autoDetectEngine,
                                                         int modelType,
                                                         int detectionType, 
                                                         int loadEngineOnCreation);

        // Import the RunInferenceImagePath_CS function
        [DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "RunInferenceImagePath_CS", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern IntPtr RunInferenceImagePath_CS(ref IntPtr handle, string imageFilePath);

        [DllImport(@"C:\ProgramData\ANSCENTER\Shared\ANSODEngine.dll", EntryPoint = "ReleaseANSODHandle", CallingConvention = CallingConvention.Cdecl)]
        public static extern int ReleaseANSODHandle(ref IntPtr handle);


        // Helper function to convert IntPtr to a C# string
        public static string PtrToStringAnsi(IntPtr ptr)
        {
            return Marshal.PtrToStringAnsi(ptr);
        }

        private IntPtr handle;

        static string CheckFileInZip(string zipFilePath)
        {
            // Ensure the zip file exists
            if (!File.Exists(zipFilePath))
            {
                //Console.WriteLine("Zip file does not exist.");
                return null; // or return string.Empty;
            }

            // Open the zip file
            using (ZipArchive archive = ZipFile.OpenRead(zipFilePath))
            {
                // Iterate through the entries in the zip file
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    // Check if the entry's name ends with .txt extension (case-insensitive)
                    if (entry.Name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
                    {
                        string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(entry.Name);
                        //Console.WriteLine($"Found .txt file: {fileNameWithoutExtension}");
                        return fileNameWithoutExtension;
                    }
                }
            }

            // No .txt file found
            //Console.WriteLine("No .txt file found inside the zip file.");
            return null; // or return string.Empty;
        }
        private int GetModelType(string modelFilePath, ref int modelType, ref int detectionType)
        {
            modelType = 5;  // Default model type
            detectionType = 1;
            if (!System.IO.File.Exists(modelFilePath))
            {
                return 0;
            }

            // Open the zip file
            string txtFileName = CheckFileInZip(modelFilePath);

            // Output the result
            if (!string.IsNullOrEmpty(txtFileName))
            {

                switch (txtFileName)
                {
                    case "openvino":
                        //Console.WriteLine("File is 'openvino'.");
                        modelType = 5;  // OPENVINO 
                        detectionType = 1;
                        break;

                    case "openvino10":
                       //Console.WriteLine("File is 'openvino10'.");
                        modelType = 15;  // Default model type
                        detectionType = 1;
                        break;

                    case "tensorrt":
                        //Console.WriteLine("File is 'tensorrt'.");
                        modelType = 4;  // TENSORRT
                        detectionType = 1;
                        break;

                    case "tensorrt10":
                        //Console.WriteLine("File is 'tensorrt10'.");
                        modelType = 14;  // Default model type
                        detectionType = 1;
                        break;

                    default:
                        //Console.WriteLine("File name does not match any known cases.");
                        modelType = 5;  // Default model type
                        detectionType = 1;
                        break;
                }
                return 1;

            }
            else
            {
                return 0;
            }


        }

        public ANSDLDOTNET() {
            handle = IntPtr.Zero;
        }
        public string Init(string licenseKey, string modelFilePath, string modelFileZipPassword, float detectionScore, int loadEngineOnCreation) {
            int modelType = 1;
            int detectionType = 1;
            string enginePath = "C:\\ProgramData\\ANSCENTER\\Shared\\ANSODEngine.dll";
            
            // 1. Check if the model file exists
            if (!System.IO.File.Exists(modelFilePath))
            {
                return "ERROR: Model file does not exist";
            }

            //2. Check if engine path exists
            if (!System.IO.File.Exists(enginePath))
            {
                return "ERROR: Engine path does not exist. Please install ANS Core Engine.";
            }

            //3. Get the model type
            GetModelType(modelFilePath, ref modelType, ref detectionType);

            IntPtr resultPtr = CreateANSODHandle_CS(ref handle,
                                               licenseKey,
                                               modelFilePath,
                                               modelFileZipPassword,
                                               0.5f,
                                               detectionScore,
                                               0.4f,
                                               1,       // autoDetectEngine
                                               modelType,       // modelType
                                               detectionType, 
                                               loadEngineOnCreation);      // load Engine on creation
            return PtrToStringAnsi(resultPtr);
        }
        public int Release()
        {
            int result = ReleaseANSODHandle(ref handle);
            return result;
        }
        // Call RunInferenceImagePath_CS to run inference on an image
        public string RunInferenceFromImage(string imageFilePath)
        {
            IntPtr inferenceResultPtr = RunInferenceImagePath_CS(ref handle, imageFilePath);
            string inferenceResult = PtrToStringAnsi(inferenceResultPtr);
            return inferenceResult;
        }

    }
}
