using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

internal delegate void SetBackgroundColor(Control ctl, Color col);

public static class WinFormsUtil {
	/// <summary>
	/// Extension method for Controls, making their background color flash twice in the designated color
	/// </summary>
	/// <param name="ctl">The control that should have its background color blink</param>
	/// <param name="col">The color to change the control's background color to</param>
	/// <param name="msDuration">The duration of the whole operation, in miliseconds</param>
	public static void BackColorBlink(this Control ctl, Color col, int msDuration = 750) {
		Color oldcol = ctl.BackColor;
		ctl.BackColor = col;
		Control ctl1 = ctl;

		SetBackgroundColor del = (Control c1, Color c2) => {
			if(c1.InvokeRequired) {
				c1.Invoke(new Action(() => c1.BackColor = c2));
			} else {
				c1.BackColor = c2;
			}
		};

		Thread t = new Thread(() => {
			Thread.Sleep(msDuration / 3);
			del(ctl1, oldcol);
			Thread.Sleep(msDuration / 3);
			del(ctl1, col);
			Thread.Sleep(msDuration / 3);
			del(ctl1, oldcol);
		});
		t.Start();
	}

	/// <summary>
	/// Invoke an Action on the UI thread if required, execute on the current thread otherwise
	/// </summary>
	/// <remarks>Use UIThreadInvoke if Control.Invoke instead of Control.BeginInvoke is required</remarks>
	public static void UIThread(this Control ctl, Action code) {
		if(ctl.InvokeRequired) {
			ctl.BeginInvoke(code);
		} else {
			code.Invoke();
		}
	}

	/// <summary>
	/// Invoke an Action on the UI thread if required, execute on the current thread otherwise
	/// </summary>
	/// <remarks>Use UIThread unless Control.Invoke instead of Control.BeginInvoke is required</remarks>
	public static void UIThreadInvoke(this Control ctl, Action code) {
		if(ctl.InvokeRequired) {
			ctl.Invoke(code);
		} else {
			code.Invoke();
		}
	}
}