/*
 * ThreadOps.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Threading;
using Eagle._Attributes;

namespace Eagle._Components.Private
{
    [ObjectId("b81d425a-8049-4404-92c7-d106402b6bba")]
    internal static class ThreadOps
    {
        #region Public Constants
        public static readonly int DefaultJoinTimeout =
#if MONO || MONO_HACKS
            CommonOps.Runtime.IsMono() ? 6000 :
#endif
            3000;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        public static bool IsStaThread()
        {
            Thread thread = Thread.CurrentThread;

            if (thread == null)
                return false;

            return (thread.GetApartmentState() == ApartmentState.STA);
        }

        ///////////////////////////////////////////////////////////////////////

        public static EventWaitHandle CreateEvent(
            bool automatic
            )
        {
            try
            {
                return new EventWaitHandle(false, automatic ?
                    EventResetMode.AutoReset : EventResetMode.ManualReset);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);

                throw;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        public static EventWaitHandle CreateEvent(
            string name
            )
        {
            return CreateEvent(name, false);
        }

        ///////////////////////////////////////////////////////////////////////

        public static EventWaitHandle CreateEvent(
            string name,
            bool automatic
            )
        {
            try
            {
                return new EventWaitHandle(false, automatic ?
                    EventResetMode.AutoReset : EventResetMode.ManualReset,
                    name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);

                throw;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        public static EventWaitHandle OpenEvent(
            string name
            )
        {
            EventWaitHandle @event = null;

            try
            {
                @event = EventWaitHandle.OpenExisting(name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

#if DEBUG && VERBOSE
            TraceOps.DebugTrace(String.Format(
                "{0}: OpenEvent: {1}, name = {2}{3}",
                GlobalState.GetCurrentThreadId(), (@event != null) ?
                    "success" : "failure", FormatOps.WrapOrNull(name),
                Environment.NewLine), typeof(ThreadOps).Name);
#endif

            return @event;
        }

        ///////////////////////////////////////////////////////////////////////

        public static void CloseEvent(
            ref EventWaitHandle @event
            )
        {
            try
            {
                if (@event != null)
                {
                    @event.Close();
                    @event = null;
                }
                else
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: CloseEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        public static bool ResetEvent(
            EventWaitHandle @event
            )
        {
            try
            {
                if (@event != null)
                    return @event.Reset();
                else
                    TraceOps.DebugTrace(String.Format(
                        "{0}: ResetEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////

        public static bool SetEvent(
            EventWaitHandle @event
            )
        {
            try
            {
                if (@event != null)
                    return @event.Set();
                else
                    TraceOps.DebugTrace(String.Format(
                        "{0}: SetEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////

        public static bool WaitEvent(
            EventWaitHandle @event
            )
        {
            try
            {
                if (@event != null)
                    return @event.WaitOne();
                else
                    TraceOps.DebugTrace(String.Format(
                        "{0}: WaitEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////

        public static bool WaitEvent(
            EventWaitHandle @event,
            int milliseconds
            )
        {
            try
            {
                if (@event != null)
#if !MONO && !MONO_HACKS && (NET_20_SP2 || NET_40)
                    return @event.WaitOne(milliseconds);
#else
                    return @event.WaitOne(milliseconds, false);
#endif
                else
                    TraceOps.DebugTrace(String.Format(
                        "{0}: WaitEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////

        public static int WaitAnyEvent(
            EventWaitHandle[] events,
            int milliseconds
            )
        {
            try
            {
                if (events != null)
#if !MONO && !MONO_HACKS && (NET_20_SP2 || NET_40)
                    return EventWaitHandle.WaitAny(events, milliseconds);
#else
                    return EventWaitHandle.WaitAny(events, milliseconds, false);
#endif
                else
                    TraceOps.DebugTrace(String.Format(
                        "{0}: WaitAnyEvent: invalid event{1}",
                        GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(ThreadOps).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(ThreadOps).Name);
            }

            return EventWaitHandle.WaitTimeout;
        }
    }
}
