using System;
using System.Runtime.InteropServices;

namespace WinSCP
{
    internal class Job : IDisposable
    {
        public Job(Logger logger, string name)
        {
            _logger = logger;
            _handle = UnsafeNativeMethods.CreateJobObject(IntPtr.Zero, name);

            if (_handle == IntPtr.Zero)
            {
                _logger.WriteLine("Cannot create job ({0})", Logger.LastWin32ErrorMessage());
            }
            else
            {
                _logger.WriteLine("Job created");

                JobObjectBasicLimitInformation info = new JobObjectBasicLimitInformation
                {
                    LimitFlags = 0x2000 // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                };

                JobObjectExtendedLimitInformation extendedInfo = new JobObjectExtendedLimitInformation
                {
                    BasicLimitInformation = info
                };

                int length = Marshal.SizeOf(typeof(JobObjectExtendedLimitInformation));
                IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                if (UnsafeNativeMethods.SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                {
                    _logger.WriteLine("Job set to kill all processes");
                }
                else
                {
                    _logger.WriteLine("Cannot set job to kill all processes ({0})", Logger.LastWin32ErrorMessage());
                }
            }
        }

        ~Job()
        {
            DoDispose();
        }

        public void Dispose()
        {
            DoDispose();
            GC.SuppressFinalize(this);
        }

        private void DoDispose()
        {
            Close();
        }

        public void Close()
        {
            _logger.WriteLine("Closing job");
            UnsafeNativeMethods.CloseHandle(_handle);
            _handle = IntPtr.Zero;
        }

        private IntPtr _handle;
        private readonly Logger _logger;
    }
}
