using UnityEngine;
using System; // For IntPtr - No longer needed here
using System.Diagnostics; // For Process - Keep if Watchdog re-enabled
using Debug = UnityEngine.Debug; // Keep alias
using Screen = UnityEngine.Screen; // Use UnityEngine.Screen directly
using System.IO; // For Path.Combine

// Make sure NativeOverlayInterface, OverlayHResult, CoVinceOverlayTextAlignment are accessible

// TODO, when start videorecording, get red border, then start screenshare, still red border
// after stop  recording, and still  screenshare, need to get green border


public class WindowsOverlayController : MonoBehaviour // Assuming _BaseController provides log/logError instance methods
{
    // --- Static Coordination State for Border ---
    // These track the *requests* for showing the border overlay for different reasons
    private static bool s_isOverlayActive = false; // Tracks if the border overlay window is currently shown via this coordinator
    private static bool s_isOverlayForRecording = false;
    private static bool s_isOverlayForSharing = false;

    // --- Instance Variables ---
    // These might be set if multiple instances are used, determines THIS instance's purpose
    public bool isForRecording;
    //private Process watchdogProcess; // Keep if needed later
    private int displayNumber = 0; // Monitor index this instance relates to (if needed)

    // Test variables - keep for Update() test code
    private bool useTestControls = true; // Toggle testing via Inspector
    public bool showText = false;
    public int fontSize = 20;

    // Define image paths using StreamingAssets for build compatibility
    private string imagePath1;
    private string imagePath2;

    public CoVinceOverlayTextAlignment textAlignment = CoVinceOverlayTextAlignment.TOP;

    
    private void Awake()
    {
        //C:/ Users / denni / AppData / LocalLow / DefaultCompany / covinceplatform
       // log ($"[WindowsOverlayController] Awake - Show File Path: " + GlobalConstants.DATA_FOLDERPATH);
    //    imagePath1 = Path.Combine(GlobalConstants.DATA_FOLDERPATH, "Images", "BurgerTEST.png");
    //    imagePath2 = Path.Combine(GlobalConstants.DATA_FOLDERPATH, "Images", "PizzaTEST.png");
    }
    

    // --- Unity Lifecycle ---

    // OnEnable can potentially signal intent if needed, but OnDestroy is more critical
    // private void OnEnable() { }

    private void OnDestroy()
    {
        // Signal that this instance's reason for showing the overlay is gone
        if (isForRecording)
        {
            s_isOverlayForRecording = false;
        }
        else // Assume it was for sharing if not for recording
        {
            s_isOverlayForSharing = false;
        }

        // Update the appearance based on remaining requests
        UpdateOverlayAppearance(displayNumber); // Pass monitor index needed by ShowOverlayOnMonitor

        // Watchdog cleanup remains commented
    }

    void OnApplicationQuit()
    {
        // Clear all requests on quit
        s_isOverlayForRecording = false;
        s_isOverlayForSharing = false;

        // Hide overlay explicitly on quit as a safety measure
        // (although DllMain DETACH also calls HideOverlay)
        OverlayHResult result = NativeOverlayInterface.HideOverlay();
        if (result != OverlayHResult.S_OK)
        {
            // Use instance logger if available, otherwise Debug.LogError
            //logError($"[WindowsOverlayController] OnApplicationQuit - HideOverlay failed (might be ok). HRESULT: 0x{(int)result:X}");
        }
    }

    // --- Static Coordination Logic for Border ---

    /// <summary>
    /// Checks the static flags and calls the Native Interface to show/hide/update
    /// the border overlay based on priority (Recording > Sharing > Hidden).
    /// </summary>
    private static void UpdateOverlayAppearance(int displayNr)
    {
        // Ensure DLL is ready before calling its functions
        if (!NativeOverlayInterface.IsSupportedPlatform) return;

        int desiredState = 0; // 0 = Hidden, 1 = ShareScreen (Green), 2 = Recording (Red)
        Color desiredColor = Color.black;
        int desiredBorderWidth = 0;

        // Determine highest priority active state
        if (s_isOverlayForRecording)
        {
            desiredState = 2;
            desiredColor = Color.red;
            desiredBorderWidth = 15; // Example width
        }
        else if (s_isOverlayForSharing)
        {
            desiredState = 1;
            desiredColor = Color.green;
            desiredBorderWidth = 10; // Example width
        }
        // else desiredState remains 0 (Hidden)

        // Call DLL via NativeOverlayInterface based on desired state
        OverlayHResult result;
        if (desiredState > 0) // Show or Update
        {
            // Call ShowOverlayOnMonitor - this function in the DLL handles both showing initially
            // and updating the state (color/width) because it calls HideOverlay internally first.
            result = NativeOverlayInterface.ShowOverlayOnMonitor(
                displayNr,          // Target monitor
                "",                 // No text for border overlay
                false,              // No text
                desiredBorderWidth,
                desiredColor,       // Pass Color struct
                1,                  // Dummy font size
                0                   // Dummy alignment
            );

            if (result == OverlayHResult.S_OK)
            {
                s_isOverlayActive = true;
            }
            else
            {
                // Use Debug.LogError as this is a static method
                //logError($"[WindowsOverlayController] UpdateOverlayAppearance - Static Update: Failed to show/update overlay. HRESULT: 0x{(int)result:X}");
                //Debug.LogError($"[WindowsOverlayController] UpdateOverlayAppearance - Static Update: Failed to show/update overlay. HRESULT: 0x{(int)result:X}");
            }
        }
        else // Hide
        {
            if (s_isOverlayActive) // Only hide if coordinator thinks it's active
            {
                result = NativeOverlayInterface.HideOverlay();
                if (result == OverlayHResult.S_OK)
                {
                    s_isOverlayActive = false;
                }
                else
                {
                    // Use Debug.LogError
                    //logError($"[WindowsOverlayController] UpdateOverlayAppearance - Static Update: Failed to hide the overlay. HRESULT: 0x{(int)result:X}");
                    //Debug.LogError($"[WindowsOverlayController] UpdateOverlayAppearance - Static Update: Failed to hide the overlay. HRESULT: 0x{(int)result:X}");
                }
            }
        }
    }


    // --- Public Methods to Control Border State ---

    /// <summary>
    /// Call this to signal the start of recording or sharing.
    /// </summary>
    public void showBorder(bool isForRecordingOverlay, int displayIndex = 0)
    {
        this.isForRecording = isForRecordingOverlay; // Store purpose of this instance
        this.displayNumber = displayIndex;

        if (isForRecordingOverlay)
        {
            s_isOverlayForRecording = true;
        }
        else
        {
            s_isOverlayForSharing = true;
        }
        UpdateOverlayAppearance(displayNumber);
    }

    /// <summary>
    /// Call this to signal the end of recording or sharing associated with this instance.
    /// </summary>
    public void hideBorder()
    {
        if (isForRecording)
        {
            s_isOverlayForRecording = false;
        }
        else
        {
            s_isOverlayForSharing = false;
        }
        // Reset instance flags
        isForRecording = false;
        // Don't reset displayNumber? Or maybe set to 0?

        UpdateOverlayAppearance(displayNumber);
    }


    // --- Direct DLL Wrappers (Optional - Can call NativeOverlayInterface directly elsewhere) ---
    // These just pass calls through and log errors using the instance logger

    public void showOverlayText(bool show)
    {
        OverlayHResult result = NativeOverlayInterface.ShowOverlayText(show);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] ShowOverlayText - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    public void updateOverlayText(string newOverlayText)
    {
        OverlayHResult result = NativeOverlayInterface.UpdateOverlayText(newOverlayText);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] UpdateOverlayText - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    public void updateOverlayTextSize(int newTextSize)
    {
        OverlayHResult result = NativeOverlayInterface.UpdateOverlayFontSize(newTextSize);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] UpdateOverlayTextSize - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    public void updateOverlayBorderColor(Color newBorderColor)
    {
        OverlayHResult result = NativeOverlayInterface.UpdateOverlayColor(newBorderColor);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] UpdateOverlayBorderColor - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    public void updateOverlayBorderWidth(int newBorderWidth)
    {
        OverlayHResult result = NativeOverlayInterface.UpdateOverlayWidth(newBorderWidth);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] UpdateOverlayBorderWidth - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    public void updateOverlayTextAlignment(CoVinceOverlayTextAlignment alignment)
    {
        OverlayHResult result = NativeOverlayInterface.UpdateOverlayAlignment(alignment);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] UpdateOverlayTextAlignment - Failed. HRESULT: 0x{(int)result:X}");
        }
    }

    // --- Pointer Wrappers (Can call NativeOverlayInterface directly elsewhere) ---

    public void addOrUpdatePointer(string userId, string userName, int x, int y, string imagePath, int desiredWidth, int desiredHeight)
    {
        OverlayHResult result = NativeOverlayInterface.AddOrUpdatePointer(userId, userName, x, y, imagePath, desiredWidth, desiredHeight);
        if (result != OverlayHResult.S_OK)
        {
            //logError($"[WindowsOverlayController] AddOrUpdatePointer - Failed for {userId}. HRESULT: 0x{(int)result:X}");
        }
    }

    public void removePointer(string userId)
    {
        OverlayHResult result = NativeOverlayInterface.RemovePointer(userId);
        if (result != OverlayHResult.S_OK)
        { // Check if RemovePointer returns error on failure
            //logError($"[WindowsOverlayController] RemovePointer - Failed for {userId}. HRESULT: 0x{(int)result:X}");
        }
    }

    public void clearAllPointers()
    {
        OverlayHResult result = NativeOverlayInterface.ClearAllPointers();
        if (result != OverlayHResult.S_OK)
        { // Check if ClearAllPointers returns error on failure
            //logError($"[WindowsOverlayController] ClearAllPointers - Failed. HRESULT: 0x{(int)result:X}");
        }
    }


    // --- Update Method for Testing ---
    
    void Update()
    {
        // Only run test controls if enabled via inspector
        if (!useTestControls) return;

        // Check if the platform is supported by the native plugin
        if (!NativeOverlayInterface.IsSupportedPlatform) return;

        // --- Test Pointer Controls ---
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetMouseButton(0))
        {
            int mouseX = (int)Input.mousePosition.x;
            int mouseY = (int)(Screen.height - Input.mousePosition.y); // Flip Y for screen coords
            // Using instance method which calls static interface method
            addOrUpdatePointer("TestUser1", "Dennis 1", mouseX, mouseY, imagePath1, 64, 64);
        }
        if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetMouseButtonUp(0)) // Basic stop on key/mouse release
        {
            removePointer("TestUser1");
        }

        if (Input.GetKeyDown(KeyCode.I))
        {
            string imagePath1 = @"C:\Users\denni\AppData\LocalLow\DefaultCompany\covinceplatform\Images\BurgerTEST.png"; // Use verbatim path
            string imagePath2 = @"C:\Users\denni\AppData\LocalLow\DefaultCompany\covinceplatform\Images\PizzaTEST.png"; // Use verbatim path
            // Verify paths before calling
            //log($"DLL Image Path 1: {imagePath1}");
            //log($"DLL Image Path 2: {imagePath2}");
            //if (!System.IO.File.Exists(imagePath1)) logError("Burger Image NOT FOUND");
            //if (!System.IO.File.Exists(imagePath2)) logError("Pizza Image NOT FOUND");

            addOrUpdatePointer("TestUser1", "Dennis 1", 100, 200, imagePath1, 128, 128);
            addOrUpdatePointer("TestUser2", "Dennis 2", 400, 600, imagePath2, 64, 64);
        }

        if (Input.GetKeyDown(KeyCode.O)) { removePointer("TestUser2"); }
        if (Input.GetKeyDown(KeyCode.P)) { clearAllPointers(); }

        // --- Test Border Controls (Using public Show/Hide Border methods) ---
        if (Input.GetKeyDown(KeyCode.R))
        {
            // Simulate starting recording (Red border)
            showBorder(true, 0); // Pass true for recording, monitor 0
            //log("Test: Show Recording Border requested.");
        }
        if (Input.GetKeyDown(KeyCode.G))
        {
            // Simulate starting sharing (Green border)
            showBorder(false, 0); // Pass false for sharing, monitor 0
            //log("Test: Show Sharing Border requested.");
        }
        if (Input.GetKeyDown(KeyCode.X))
        {
            // Simulate stopping whatever THIS instance was responsible for
            hideBorder();
            //log("Test: Hide Border requested.");
        }

        // Test direct Update calls (Using public wrapper methods)
        if (Input.GetKeyDown(KeyCode.B)) { updateOverlayBorderColor(Color.blue); }
        if (Input.GetKeyDown(KeyCode.W)) { updateOverlayBorderWidth(UnityEngine.Random.Range(5, 25)); } // Example width change
        if (Input.GetKeyDown(KeyCode.H)) { showOverlayText(!showText); showText = !showText; } // Toggle text visibility
        if (Input.GetKeyDown(KeyCode.T)) { updateOverlayText($"Test {Time.time:F1}"); }

        // Alignment cycle remains complex, keep as is for testing if needed
        if (Input.GetKeyDown(KeyCode.A))
        {
            textAlignment = textAlignment switch
            {
                // If current is Center (CENTER | VCENTER), next is Top (CENTER | TOP)
                CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.VCENTER =>
                    CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.TOP,

                // If current is Top (CENTER | TOP), next is Top Right (RIGHT | TOP)
                CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.TOP =>
                    CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.VCENTER,

                // If current is Top Right (RIGHT | TOP), next is Right (RIGHT | VCENTER)
                CoVinceOverlayTextAlignment.RIGHT | CoVinceOverlayTextAlignment.TOP =>
                    CoVinceOverlayTextAlignment.RIGHT | CoVinceOverlayTextAlignment.VCENTER,

                // If current is Right (RIGHT | VCENTER), next is Bottom Right (RIGHT | BOTTOM)
                CoVinceOverlayTextAlignment.RIGHT | CoVinceOverlayTextAlignment.VCENTER =>
                    CoVinceOverlayTextAlignment.RIGHT | CoVinceOverlayTextAlignment.BOTTOM,

                // If current is Bottom Right (RIGHT | BOTTOM), next is Bottom (CENTER | BOTTOM)
                CoVinceOverlayTextAlignment.RIGHT | CoVinceOverlayTextAlignment.BOTTOM =>
                    CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.BOTTOM,

                // If current is Bottom (CENTER | BOTTOM), next is Bottom Left (LEFT | BOTTOM)
                CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.BOTTOM =>
                    CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.BOTTOM,

                // If current is Bottom Left (LEFT | BOTTOM), next is Left (LEFT | VCENTER)
                CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.BOTTOM =>
                    CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.VCENTER,

                // If current is Left (LEFT | VCENTER), next is Top Left (LEFT | TOP)
                CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.VCENTER =>
                    CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.TOP,

                // If current is Top Left (LEFT | TOP), next is Center (CENTER | VCENTER)
                CoVinceOverlayTextAlignment.LEFT | CoVinceOverlayTextAlignment.TOP =>
                    CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.VCENTER,

                // Default case (e.g., if starting state wasn't one of the above) -> go to Center (CENTER | VCENTER)
                _ => CoVinceOverlayTextAlignment.CENTER | CoVinceOverlayTextAlignment.VCENTER,
            };


            updateOverlayTextAlignment(textAlignment);
            //log($"Test: Alignment Changed to {(int)textAlignment} ({textAlignment})");
        }
        if (Input.GetKeyDown(KeyCode.F))
        {
            fontSize += 2;
            updateOverlayTextSize(fontSize);
            //log($"Test: Font Size Changed to {fontSize}");
        }

    } // End Update()
    

} // End Class