/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

#pragma warning disable 618

namespace Apache.Geode.DUnitFramework
{
  using NUnit.Framework;

  public class UnitThread : ClientBase
  {
    #region Private members

    private ManualResetEvent m_start;
    private ManualResetEvent m_end;
    private Thread m_thread;
    private volatile bool m_endThread;
    private Delegate m_currDeleg;
    private object[] m_currParams;
    private object m_result;
    private Exception m_exception;

    private const string _m_disposeExceptionStr = "Thread has exited since the object has been Disposed";

    #endregion

    /// <summary>
    /// A global dictionary of threads maintained so that the list of managed
    /// threads (at least created using <c>UnitThread</c> can be obtained.
    /// </summary>
    public static Dictionary<Thread, bool> GlobalUnitThreads
      = new Dictionary<Thread, bool>();

    public UnitThread()
    {
      m_start = new ManualResetEvent(false);
      m_end = new ManualResetEvent(true);
      m_endThread = false;
      m_currDeleg = null;
      m_thread = new Thread(new ThreadStart(ThreadMain));
      m_thread.Start();
      lock (((ICollection)GlobalUnitThreads).SyncRoot)
      {
        GlobalUnitThreads.Add(m_thread, true);
      }
    }

    public static UnitThread Create()
    {
      return new UnitThread();
    }

    private void ThreadMain()
    {
      while (true)
      {
        m_start.WaitOne();
        if (m_endThread)
        {
          lock (((ICollection)GlobalUnitThreads).SyncRoot)
          {
            GlobalUnitThreads.Remove(m_thread);
          }
          return;
        }
        m_start.Reset();
        m_exception = null;
        if (m_currDeleg != null)
        {
          try
          {
            if (m_result != null)
            {
              m_result = m_currDeleg.DynamicInvoke(m_currParams);
            }
            else
            {
              m_currDeleg.DynamicInvoke(m_currParams);
            }
          }
          catch (Exception ex)
          {
            m_exception = ex;
          }
        }
        m_end.Set();
      }
    }

    #region ClientBase Members

    public override void RemoveObjectID(int objectID)
    {
      // TODO: Nothing for now.
    }

    public override void CallFn(Delegate deleg, params object[] paramList)
    {
      object result = null;
      CallFnP(deleg, paramList, ref result);
    }

    public override object CallFnR(Delegate deleg, params object[] paramList)
    {
      object result = true;
      CallFnP(deleg, paramList, ref result);
      return result;
    }

    public override string HostName
    {
      get
      {
        return "localhost";
      }
    }

    public override void SetLogFile(string logFile)
    {
      // Nothing for now since this shall be done anyway at the process level
      //Util.LogFile = logFile;
    }

    public override void SetLogLevel(Util.LogLevel logLevel)
    {
      // Nothing for now since this shall be done anyway at the process level
      //Util.CurrentLogLevel = logLevel;
    }

    public override void DumpStackTrace()
    {
      string trace = GetStackTrace();
      if (trace != null)
      {
        Util.Log(trace);
      }
    }

    public static string GetStackTrace(Thread thread)
    {
      string traceStr = null;
      try
      {
        thread.Suspend();
      }
      catch
      {
      }
      StackTrace trace = new StackTrace(thread, true);
      traceStr = string.Format("Dumping stack for managed thread [{0}]:{1}{2}",
        thread.ManagedThreadId, Environment.NewLine, trace.ToString());
      try
      {
        thread.Resume();
      }
      catch
      {
      }
      return traceStr;
    }

    public string GetStackTrace()
    {
      if (!m_endThread)
      {
        return GetStackTrace(m_thread);
      }
      return null;
    }

    public override void ForceKill(int waitMillis)
    {
      if (!m_endThread)
      {
        bool failed = true;
        m_endThread = true;
        m_start.Set();
        if (waitMillis > 0 && m_thread.Join(waitMillis))
        {
          failed = false;
        }
        if (failed)
        {
          m_exception = new ClientTimeoutException(
            "Timeout occurred in calling '" + m_currDeleg.Method.ToString() +
            '\'');
          m_end.Set();
        }
      }
    }

    public override ClientBase CreateNew(string clientId)
    {
      ClientBase newClient = new UnitThread();
      newClient.ID = clientId;
      return newClient;
    }

    public override void TestCleanup()
    {
    }

    public override void Exit()
    {
      if (!m_endThread)
      {
        m_endThread = true;
        m_start.Set();
      }
    }

    public override string ID
    {
      get
      {
        return base.ID;
      }
      set
      {
        base.ID = value;
        m_thread.Name = value;
      }
    }

    #endregion

    private void CallFnP(Delegate deleg, object[] paramList, ref object result)
    {
      lock (m_end)
      {
        if (m_endThread)
        {
          throw new ClientExitedException(_m_disposeExceptionStr);
        }
        m_end.WaitOne();
        m_end.Reset();
        m_currDeleg = deleg;
        m_currParams = paramList;
        m_result = result;
        m_start.Set();
      }
      m_end.WaitOne();
      if (m_exception != null)
      {
        throw m_exception;
      }
      if (result != null)
      {
        result = m_result;
      }
    }
  }
}
