﻿#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
#endif
using UnityEngine;

namespace AsmodeeDigital.Common.Plugin.Utils
{
    public class PlaceWindow : MonoBehaviour
    {
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        private static extern bool SetWindowPos(IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
        [DllImport("user32.dll")]
        private static extern IntPtr GetActiveWindow();

        [DllImport("user32")]
        private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lpRect, MonitorEnumProc callback, int dwData);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool EnumWindows(EnumWindowsProc callback, IntPtr extraData);

        private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
        private delegate bool MonitorEnumProc(IntPtr hDesktop, IntPtr hdc, ref Rect pRect, int dwData);

        public List<MonitorInfo> ActualScreens = new List<MonitorInfo>();

        [StructLayout(LayoutKind.Sequential)]
        private struct Rect
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        public class MonitorInfo
        {
            public bool IsPrimary = false;
            public UnityEngine.Rect Bounds = new UnityEngine.Rect();
        }

        void Start()
        {
            EnumWindows(EnumWindowsCallBack, IntPtr.Zero);
        }

        public bool EnumWindowsCallBack(IntPtr hWnd, IntPtr lParam)
        {
            int procid;
            GetWindowThreadProcessId(new HandleRef(this, hWnd), out procid);

            int currentPID = System.Diagnostics.Process.GetCurrentProcess().Id;

            if (procid == currentPID)
            {
                SetWindow(hWnd);

                return false;
            }

            return true;
        }

        private void SetWindow(IntPtr hWnd)
        {
            Screen.SetResolution(600, 350, false);

            RefreshActualScreens();

            ActualScreens.Sort((mi1, mi2) => mi1.Bounds.x.CompareTo(mi2.Bounds.x));
            MonitorInfo leftMonitorInfo = ActualScreens[0];

            if (Environment.CommandLine.Contains("user1"))
            {
                SetPosition(hWnd, (int)leftMonitorInfo.Bounds.x, (int)leftMonitorInfo.Bounds.y);
            }
            else if (Environment.CommandLine.Contains("user2"))
            {
                SetPosition(hWnd, (int)leftMonitorInfo.Bounds.x + 603, (int)leftMonitorInfo.Bounds.y);
            }
        }

        public void RefreshActualScreens()
        {
            ActualScreens.Clear();
            MonitorEnumProc callback = (IntPtr hDesktop, IntPtr hdc, ref Rect prect, int d) =>
            {
                ActualScreens.Add(new MonitorInfo()
                {
                    Bounds = new UnityEngine.Rect(prect.left, prect.top, prect.right - prect.left, prect.bottom - prect.top),
                    IsPrimary = (prect.left == 0) && (prect.top == 0),
                });

                return true;
            };

            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, callback, 0);
        }

        public void SetPosition(IntPtr hWnd, int x, int y, int resX = 0, int resY = 0)
        {
            SetWindowPos(hWnd, 0, x, y, resX, resY, resX * resY == 0 ? 1 : 0);
        }
#endif
    }
}
