using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO.Pipes;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace OverlayCS
{
    public partial class Form1 : Form
    {
        private Process _process;
        private Thread _procMonThread;

        #region Native functions
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool GetClientRect(IntPtr hWnd, ref Rectangle lpRect);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);
        #endregion

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _procMonThread = new Thread(this.ProcMonThreadFunc);
            _procMonThread.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_procMonThread != null)
            {
                _procMonThread.Abort();
                _procMonThread = null;
            }
        }

        delegate void FormUpdateCallback();

        private void UpdateWindow()
        {
            if (_process != null && _process.HasExited == false)
            {
                Rectangle cRect = new Rectangle();
                GetClientRect(_process.MainWindowHandle, ref cRect);
                if (cRect.Size.IsEmpty)   // true of _process window is minimized
                {
                    this.Hide();
                }
                else
                {
                    this.WindowState = FormWindowState.Normal;
                    this.Show();
                    Point topLeft = new Point(0, 0);
                    ClientToScreen(_process.MainWindowHandle, ref topLeft);
                    Rectangle oRect = new Rectangle(topLeft, cRect.Size);
                    if (base.Location != oRect.Location || base.Size != oRect.Size)
                    {
                        base.Location = oRect.Location;
                        base.Size = oRect.Size;
                        base.Invalidate();
                    }
                }
            }
            else
            {
                this.Visible = false;
            }
        }

        private void ProcMonThreadFunc(object data)
        {
            while (_process == null || _process.HasExited)
            {
                try
                {
                    _process = Process.GetProcessesByName("notepad")[0];
                }
                catch
                {
                    _process = null;
                }
                Thread.Sleep(2000);
            }

            Rectangle lastRect = new Rectangle();
            Rectangle rect = new Rectangle();
            while (_process != null && _process.HasExited == false)
            {
                GetWindowRect(_process.MainWindowHandle, ref rect);
                if (lastRect != rect)
                {
                    lastRect = rect;
                    Invoke(new FormUpdateCallback(UpdateWindow));
                }
                Thread.Sleep(1000);
            }
        }
    }
}