using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using TaskSchedulerInterop;

namespace TaskScheduler
{
	[ComVisible(true)]
	public class Task : IDisposable
	{
		[Flags]
		public enum PropPages
		{
			Task = 1,
			Schedule = 2,
			Settings = 4
		}

		private ITask iTask;

		private string name;

		private TriggerList triggers;

		public string Name
		{
			get
			{
				return this.name;
			}
		}

		public TriggerList Triggers
		{
			get
			{
				bool flag = this.triggers == null;
				if (flag)
				{
					this.triggers = new TriggerList(this.iTask);
				}
				return this.triggers;
			}
		}

		public string ApplicationName
		{
			get
			{
				IntPtr lpwstr;
				this.iTask.GetApplicationName(out lpwstr);
				return CoTaskMem.LPWStrToString(lpwstr);
			}
			set
			{
				this.iTask.SetApplicationName(value);
			}
		}

		public string AccountName
		{
			get
			{
				IntPtr zero = IntPtr.Zero;
				this.iTask.GetAccountInformation(out zero);
				return CoTaskMem.LPWStrToString(zero);
			}
		}

		public string Comment
		{
			get
			{
				IntPtr lpwstr;
				this.iTask.GetComment(out lpwstr);
				return CoTaskMem.LPWStrToString(lpwstr);
			}
			set
			{
				this.iTask.SetComment(value);
			}
		}

		public string Creator
		{
			get
			{
				IntPtr lpwstr;
				this.iTask.GetCreator(out lpwstr);
				return CoTaskMem.LPWStrToString(lpwstr);
			}
			set
			{
				this.iTask.SetCreator(value);
			}
		}

		private short ErrorRetryCount
		{
			get
			{
				ushort num;
				this.iTask.GetErrorRetryCount(out num);
				return (short)num;
			}
			set
			{
				this.iTask.SetErrorRetryCount((ushort)value);
			}
		}

		private short ErrorRetryInterval
		{
			get
			{
				ushort num;
				this.iTask.GetErrorRetryInterval(out num);
				return (short)num;
			}
			set
			{
				this.iTask.SetErrorRetryInterval((ushort)value);
			}
		}

		public int ExitCode
		{
			get
			{
				uint result = 0u;
				this.iTask.GetExitCode(out result);
				return (int)result;
			}
		}

		public TaskFlags Flags
		{
			get
			{
				uint result;
				this.iTask.GetFlags(out result);
				return (TaskFlags)result;
			}
			set
			{
				this.iTask.SetFlags((uint)value);
			}
		}

		public short IdleWaitMinutes
		{
			get
			{
				ushort num;
				ushort num2;
				this.iTask.GetIdleWait(out num, out num2);
				return (short)num;
			}
			set
			{
				ushort deadlineMinutes = (ushort)this.IdleWaitDeadlineMinutes;
				this.iTask.SetIdleWait((ushort)value, deadlineMinutes);
			}
		}

		public short IdleWaitDeadlineMinutes
		{
			get
			{
				ushort num;
				ushort num2;
				this.iTask.GetIdleWait(out num, out num2);
				return (short)num2;
			}
			set
			{
				ushort idleMinutes = (ushort)this.IdleWaitMinutes;
				this.iTask.SetIdleWait(idleMinutes, (ushort)value);
			}
		}

		public TimeSpan MaxRunTime
		{
			get
			{
				uint num;
				this.iTask.GetMaxRunTime(out num);
				return new TimeSpan((long)((ulong)num * 10000uL));
			}
			set
			{
				double totalMilliseconds = value.TotalMilliseconds;
				bool flag = totalMilliseconds >= 4294967295.0;
				if (flag)
				{
					this.iTask.SetMaxRunTime(4294967295u);
				}
				else
				{
					this.iTask.SetMaxRunTime((uint)totalMilliseconds);
				}
			}
		}

		public bool MaxRunTimeLimited
		{
			get
			{
				uint num;
				this.iTask.GetMaxRunTime(out num);
				return num == 4294967295u;
			}
			set
			{
				if (value)
				{
					uint num;
					this.iTask.GetMaxRunTime(out num);
					bool flag = num == 4294967295u;
					if (flag)
					{
						this.iTask.SetMaxRunTime(25920000u);
					}
				}
				else
				{
					this.iTask.SetMaxRunTime(4294967295u);
				}
			}
		}

		public DateTime MostRecentRunTime
		{
			get
			{
				SystemTime systemTime = default(SystemTime);
				this.iTask.GetMostRecentRunTime(ref systemTime);
				bool flag = systemTime.Year == 0;
				DateTime result;
				if (flag)
				{
					result = DateTime.MinValue;
				}
				else
				{
					result = new DateTime((int)systemTime.Year, (int)systemTime.Month, (int)systemTime.Day, (int)systemTime.Hour, (int)systemTime.Minute, (int)systemTime.Second, (int)systemTime.Milliseconds);
				}
				return result;
			}
		}

		public DateTime NextRunTime
		{
			get
			{
				SystemTime systemTime = default(SystemTime);
				this.iTask.GetNextRunTime(ref systemTime);
				bool flag = systemTime.Year == 0;
				DateTime result;
				if (flag)
				{
					result = DateTime.MinValue;
				}
				else
				{
					result = new DateTime((int)systemTime.Year, (int)systemTime.Month, (int)systemTime.Day, (int)systemTime.Hour, (int)systemTime.Minute, (int)systemTime.Second, (int)systemTime.Milliseconds);
				}
				return result;
			}
		}

		public string Parameters
		{
			get
			{
				IntPtr lpwstr;
				this.iTask.GetParameters(out lpwstr);
				return CoTaskMem.LPWStrToString(lpwstr);
			}
			set
			{
				this.iTask.SetParameters(value);
			}
		}

		public ProcessPriorityClass Priority
		{
			get
			{
				uint result;
				this.iTask.GetPriority(out result);
				return (ProcessPriorityClass)result;
			}
			set
			{
				bool flag = value == ProcessPriorityClass.AboveNormal || value == ProcessPriorityClass.BelowNormal;
				if (flag)
				{
					throw new ArgumentException("Unsupported Priority Level");
				}
				this.iTask.SetPriority((uint)value);
			}
		}

		public TaskStatus Status
		{
			get
			{
				int result;
				this.iTask.GetStatus(out result);
				return (TaskStatus)result;
			}
		}

		private int FlagsEx
		{
			get
			{
				uint result;
				this.iTask.GetTaskFlags(out result);
				return (int)result;
			}
			set
			{
				this.iTask.SetTaskFlags((uint)value);
			}
		}

		public string WorkingDirectory
		{
			get
			{
				IntPtr lpwstr;
				this.iTask.GetWorkingDirectory(out lpwstr);
				return CoTaskMem.LPWStrToString(lpwstr);
			}
			set
			{
				this.iTask.SetWorkingDirectory(value);
			}
		}

		public bool Hidden
		{
			get
			{
				return (this.Flags & TaskFlags.Hidden) > (TaskFlags)0;
			}
			set
			{
				if (value)
				{
					this.Flags |= TaskFlags.Hidden;
				}
				else
				{
					this.Flags &= ~TaskFlags.Hidden;
				}
			}
		}

		public object Tag
		{
			get
			{
				ushort num;
				IntPtr source;
				this.iTask.GetWorkItemData(out num, out source);
				byte[] array = new byte[(int)num];
				Marshal.Copy(source, array, 0, (int)num);
				MemoryStream serializationStream = new MemoryStream(array, false);
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				return binaryFormatter.Deserialize(serializationStream);
			}
			set
			{
				bool flag = !value.GetType().IsSerializable;
				if (flag)
				{
					throw new ArgumentException("Objects set as Data for Tasks must be serializable", "value");
				}
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				MemoryStream memoryStream = new MemoryStream();
				binaryFormatter.Serialize(memoryStream, value);
				this.iTask.SetWorkItemData((ushort)memoryStream.Length, memoryStream.GetBuffer());
			}
		}

		internal Task(ITask iTask, string taskName)
		{
			this.iTask = iTask;
			bool flag = taskName.EndsWith(".job");
			if (flag)
			{
				this.name = taskName.Substring(0, taskName.Length - 4);
			}
			else
			{
				this.name = taskName;
			}
			this.triggers = null;
			this.Hidden = this.GetHiddenFileAttr();
		}

		private void SetHiddenFileAttr(bool set)
		{
			IPersistFile persistFile = (IPersistFile)this.iTask;
			string path;
			persistFile.GetCurFile(out path);
			FileAttributes fileAttributes = File.GetAttributes(path);
			if (set)
			{
				fileAttributes |= FileAttributes.Hidden;
			}
			else
			{
				fileAttributes &= ~FileAttributes.Hidden;
			}
			File.SetAttributes(path, fileAttributes);
		}

		private bool GetHiddenFileAttr()
		{
			IPersistFile persistFile = (IPersistFile)this.iTask;
			string path;
			persistFile.GetCurFile(out path);
			bool result;
			try
			{
				FileAttributes attributes = File.GetAttributes(path);
				result = ((attributes & FileAttributes.Hidden) > (FileAttributes)0);
			}
			catch
			{
				result = false;
			}
			return result;
		}

		public DateTime NextRunTimeAfter(DateTime after)
		{
			after = after.AddSeconds(1.0);
			SystemTime systemTime = default(SystemTime);
			systemTime.Year = (ushort)after.Year;
			systemTime.Month = (ushort)after.Month;
			systemTime.Day = (ushort)after.Day;
			systemTime.DayOfWeek = (ushort)after.DayOfWeek;
			systemTime.Hour = (ushort)after.Hour;
			systemTime.Minute = (ushort)after.Minute;
			systemTime.Second = (ushort)after.Second;
			SystemTime systemTime2 = default(SystemTime);
			systemTime2 = systemTime;
			systemTime2.Year = (ushort)DateTime.MaxValue.Year;
			systemTime2.Month = 1;
			ushort num = 1;
			IntPtr ptr;
			this.iTask.GetRunTimes(ref systemTime, ref systemTime2, ref num, out ptr);
			bool flag = num == 1;
			DateTime result;
			if (flag)
			{
				SystemTime systemTime3 = default(SystemTime);
				systemTime3 = (SystemTime)Marshal.PtrToStructure(ptr, typeof(SystemTime));
				Marshal.FreeCoTaskMem(ptr);
				result = new DateTime((int)systemTime3.Year, (int)systemTime3.Month, (int)systemTime3.Day, (int)systemTime3.Hour, (int)systemTime3.Minute, (int)systemTime3.Second);
			}
			else
			{
				result = DateTime.MinValue;
			}
			return result;
		}

		public void Run()
		{
			this.iTask.Run();
		}

		public void Save()
		{
			IPersistFile persistFile = (IPersistFile)this.iTask;
			persistFile.Save(null, false);
			this.SetHiddenFileAttr(this.Hidden);
		}

		public void Save(string name)
		{
			IPersistFile persistFile = (IPersistFile)this.iTask;
			string path;
			persistFile.GetCurFile(out path);
			string pszFileName = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar.ToString() + name + Path.GetExtension(path);
			persistFile.Save(pszFileName, true);
			persistFile.SaveCompleted(pszFileName);
			this.name = name;
			this.SetHiddenFileAttr(this.Hidden);
		}

		public void Close()
		{
			bool flag = this.triggers != null;
			if (flag)
			{
				this.triggers.Dispose();
			}
			Marshal.ReleaseComObject(this.iTask);
			this.iTask = null;
		}

		public void DisplayForEdit()
		{
			this.iTask.EditWorkItem(0u, 0u);
		}

		public bool DisplayPropertySheet()
		{
			return this.DisplayPropertySheet(Task.PropPages.Task | Task.PropPages.Schedule | Task.PropPages.Settings);
		}

		public bool DisplayPropertySheet(Task.PropPages pages)
		{
			PropSheetHeader propSheetHeader = default(PropSheetHeader);
			IProvideTaskPage provideTaskPage = (IProvideTaskPage)this.iTask;
			IntPtr[] array = new IntPtr[3];
			int num = 0;
			bool flag = (pages & Task.PropPages.Task) > (Task.PropPages)0;
			if (flag)
			{
				IntPtr intPtr;
				provideTaskPage.GetPage(0, false, out intPtr);
				array[num++] = intPtr;
			}
			bool flag2 = (pages & Task.PropPages.Schedule) > (Task.PropPages)0;
			if (flag2)
			{
				IntPtr intPtr;
				provideTaskPage.GetPage(1, false, out intPtr);
				array[num++] = intPtr;
			}
			bool flag3 = (pages & Task.PropPages.Settings) > (Task.PropPages)0;
			if (flag3)
			{
				IntPtr intPtr;
				provideTaskPage.GetPage(2, false, out intPtr);
				array[num++] = intPtr;
			}
			bool flag4 = num == 0;
			if (flag4)
			{
				throw new ArgumentException("No Property Pages to display");
			}
			propSheetHeader.dwSize = (uint)Marshal.SizeOf(propSheetHeader);
			propSheetHeader.dwFlags = 128u;
			propSheetHeader.pszCaption = this.Name;
			propSheetHeader.nPages = (uint)num;
			GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
			propSheetHeader.phpage = gCHandle.AddrOfPinnedObject();
			int num2 = PropertySheetDisplay.PropertySheet(ref propSheetHeader);
			gCHandle.Free();
			bool flag5 = num2 < 0;
			if (flag5)
			{
				throw new Exception("Property Sheet failed to display");
			}
			return num2 > 0;
		}

		public void SetAccountInformation(string accountName, string password)
		{
			IntPtr intPtr = Marshal.StringToCoTaskMemUni(password);
			this.iTask.SetAccountInformation(accountName, intPtr);
			Marshal.FreeCoTaskMem(intPtr);
		}

		public void SetAccountInformation(string accountName, SecureString password)
		{
			IntPtr intPtr = Marshal.SecureStringToCoTaskMemUnicode(password);
			this.iTask.SetAccountInformation(accountName, intPtr);
			Marshal.ZeroFreeCoTaskMemUnicode(intPtr);
		}

		public void Terminate()
		{
			this.iTask.Terminate();
		}

		public override string ToString()
		{
			return string.Format("{0} (\"{1}\" {2})", this.name, this.ApplicationName, this.Parameters);
		}

		public void Dispose()
		{
			this.Close();
		}
	}
}
