/*
 * 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.Reflection;
using System.Threading;

namespace Apache.Geode.DUnitFramework
{
  /// <summary>
  /// Delegate to be invoked on the client side. This one is for
  /// a parameterless function that doesn't return any value.
  /// </summary>
  public delegate void UnitFnMethod();
  public delegate void UnitFnMethod<T1>(T1 param1);
  public delegate void UnitFnMethod<T1, T2>(T1 param1,
    T2 param2);
  public delegate void UnitFnMethod<T1, T2, T3>(T1 param1,
    T2 param2, T3 param3);
  public delegate void UnitFnMethod<T1, T2, T3, T4>(T1 param1,
    T2 param2, T3 param3, T4 param4);
  public delegate void UnitFnMethod<T1, T2, T3, T4, T5>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5);
  public delegate void UnitFnMethod<T1, T2, T3, T4, T5, T6>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6);
  public delegate void UnitFnMethod<T1, T2, T3, T4, T5, T6, T7>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7);

  /*
  public delegate void UnitFnMethodGeneric<TKey, TVal, T1, T2, T3, T4, T5, T6, T7>(T1<TKey, TVal> param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7);
   * */

  public delegate void UnitFnMethod<T1, T2, T3, T4, T5, T6, T7, T8>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8);
  public delegate void UnitFnMethod<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8, T9 param9);

  /// <summary>
  /// Delegate to be invoked on the client side. This one is for a function
  /// with arbitrary number of parameters that returns an object.
  /// </summary>
  /// <param name="data">Any data that needs to be passed to the function.</param>
  /// <returns>The result of the function as an 'object'.</returns>
  public delegate T0 UnitFnMethodR<T0>();
  public delegate T0 UnitFnMethodR<T0, T1>(T1 param1);
  public delegate T0 UnitFnMethodR<T0, T1, T2>(T1 param1,
    T2 param2);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3>(T1 param1,
    T2 param2, T3 param3);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4>(T1 param1,
    T2 param2, T3 param3, T4 param4);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4, T5>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7);

  /*
  public delegate T0 UnitFnMethodRUnitFnMethodGeneric<TKey, TVal, T0, T1, T2, T3, T4, T5, T6, T7>(T1<TKey, TVal> param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7);
   * */

  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7, T8>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8);
  public delegate T0 UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 param1,
    T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8, T9 param9);

  /// <summary>
  /// An abstract class to encapsulate calling a function on a client
  /// thread/process/... Example implementations would be a 'Thread'
  /// or a process on a remote host.
  /// 
  /// Implementations are expected to catch the NUnit.Framework.AssertionException
  /// exception thrown by the client thread/process/... and throw them in the
  /// calling thread (i.e. in the function calls).
  /// </summary>
  public abstract class ClientBase : IDisposable
  {
    #region Private members

    private string m_id;
    private int m_numTasksRunning;

    #endregion

    #region Public accessors

    public virtual string ID
    {
      get
      {
        return m_id;
      }
      set
      {
        m_id = value;
      }
    }

    public bool TaskRunning
    {
      get
      {
        return (m_numTasksRunning > 0);
      }
    }

    public virtual string StartDir
    {
      get
      {
        return null;
      }
    }

    #endregion

    #region Call functions with no result

    /// <summary>
    /// Call a 'UnitFunction' on this thread/process/... blocking till
    /// the function completes.
    /// </summary>
    /// <param name="deleg">The function to run on this thread/process/...</param>
    /// <exception cref="ClientExitedException">
    /// If the client has exited due to some exception or if the object has been destroyed.
    /// </exception>
    public void Call(UnitFnMethod deleg)
    {
      CallFn(deleg, null);
    }

    public void Call<T1>(UnitFnMethod<T1> deleg, T1 param1)
    {
      CallFn(deleg, new object[] { param1 });
    }

    public void Call<T1, T2>(UnitFnMethod<T1, T2> deleg,
        T1 param1, T2 param2)
    {
      CallFn(deleg, new object[] { param1, param2 });
    }

    public void Call<T1, T2, T3>(UnitFnMethod<T1, T2, T3> deleg,
        T1 param1, T2 param2, T3 param3)
    {
      CallFn(deleg, new object[] { param1, param2, param3 });
    }

    public void Call<T1, T2, T3, T4>(UnitFnMethod<T1, T2, T3, T4> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4 });
    }

    public void Call<T1, T2, T3, T4, T5>(UnitFnMethod<T1, T2, T3, T4, T5> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4, T5 param5)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4, param5 });
    }

    public void Call<T1, T2, T3, T4, T5, T6>(UnitFnMethod<T1, T2, T3, T4, T5, T6> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4, param5, param6 });
    }

    public void Call<T1, T2, T3, T4, T5, T6, T7>(UnitFnMethod<T1, T2, T3, T4, T5, T6, T7> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7 });
    }

    public void Call<T1, T2, T3, T4, T5, T6, T7, T8>(UnitFnMethod<T1, T2, T3, T4, T5, T6, T7, T8> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7, param8 });
    }

    public void Call<T1, T2, T3, T4, T5, T6, T7, T8, T9>(UnitFnMethod<T1, T2, T3, T4, T5, T6, T7, T8, T9> deleg,
        T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8, T9 param9)
    {
      CallFn(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7, param8, param9 });
    }

    #endregion

    #region Call functions that return a result

    public void Call<T0>(UnitFnMethodR<T0> deleg,
      out T0 outparam)
    {
      outparam = (T0)CallFnR(deleg, null);
    }

    public void Call<T0, T1>(UnitFnMethodR<T0, T1> deleg,
      out T0 outparam, T1 param1)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1 });
    }

    public void Call<T0, T1, T2>(UnitFnMethodR<T0, T1, T2> deleg,
      out T0 outparam, T1 param1, T2 param2)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2 });
    }

    public void Call<T0, T1, T2, T3>(UnitFnMethodR<T0, T1, T2, T3> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3 });
    }

    public void Call<T0, T1, T2, T3, T4>(UnitFnMethodR<T0, T1, T2, T3, T4> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4 });
    }

    public void Call<T0, T1, T2, T3, T4, T5>(UnitFnMethodR<T0, T1, T2, T3, T4, T5> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4, param5 });
    }

    public void Call<T0, T1, T2, T3, T4, T5, T6>(UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4, param5, param6 });
    }

    public void Call<T0, T1, T2, T3, T4, T5, T6, T7>(UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7 });
    }

    public void Call<T0, T1, T2, T3, T4, T5, T6, T7, T8>(UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7, T8> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7, param8 });
    }

    public void Call<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(UnitFnMethodR<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> deleg,
      out T0 outparam, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5, T6 param6, T7 param7, T8 param8, T9 param9)
    {
      outparam = (T0)CallFnR(deleg, new object[] { param1, param2, param3, param4, param5, param6, param7, param8, param9 });
    }

    #endregion

    public void RemoveObject(object obj)
    {
      if (obj != null)
      {
        RemoveObjectID(obj.GetHashCode());
      }
    }

    public void RemoveType(Type tp)
    {
      if (tp != null)
      {
        RemoveObjectID(tp.GetHashCode());
      }
    }

    public virtual void IncrementTasksRunning()
    {
      Interlocked.Increment(ref m_numTasksRunning);
    }

    public virtual void DecrementTasksRunning()
    {
      Interlocked.Decrement(ref m_numTasksRunning);
    }

    public static void GetDelegateInfo(Delegate deleg, out string assemblyName,
        out string typeName, out string methodName, out int objectId)
    {
      MethodInfo mInfo = deleg.Method;
      object target = deleg.Target;
      Type delegType;

      if (target != null)
      {
        // Do not use ReflectedType, otherwise it returns base class type
        // for a derived class object when the derived class does not
        // override the method.
        delegType = target.GetType();
        objectId = target.GetHashCode();
      }
      else
      {
        // This case would be for static methods.
        delegType = mInfo.ReflectedType;
        objectId = delegType.GetHashCode();
      }
      assemblyName = delegType.Assembly.FullName;
      typeName = delegType.FullName;
      methodName = mInfo.Name;
    }

    public abstract void RemoveObjectID(int objectID);

    public abstract void CallFn(Delegate deleg, object[] paramList);

    public abstract object CallFnR(Delegate deleg, object[] paramList);

    public abstract string HostName
    {
      get;
    }

    /// <summary>
    /// Set the path of the log file.
    /// </summary>
    /// <param name="logPath">The path of the log file.</param>
    public abstract void SetLogFile(string logPath);

    /// <summary>
    /// Set logging level for the client.
    /// </summary>
    /// <param name="logLevel">The logging level to set.</param>
    public abstract void SetLogLevel(Util.LogLevel logLevel);

    /// <summary>
    /// Dump the stack trace of the client in the file set using the
    /// <see cref="SetLogFile"/> functions (or to console if not set).
    /// </summary>
    public abstract void DumpStackTrace();

    /// <summary>
    /// Kill the client after waiting for it to exit cleanly for the given
    /// milliseconds. This function should also dispose the object so that
    /// no other functions can be invoked on it.
    /// </summary>
    /// <param name="waitMillis">
    /// The number of milliseconds to wait before forcibly killing the client.
    /// A value of less than or equal to 0 means immediately killing.
    /// </param>
    public abstract void ForceKill(int waitMillis);

    /// <summary>
    /// Create a new client from the current instance.
    /// </summary>
    /// <param name="clientId">The ID of the new client.</param>
    /// <returns>An instance of a new client.</returns>
    public abstract ClientBase CreateNew(string clientId);

    /// <summary>
    /// Any actions required to be done to cleanup at the end of each test.
    /// </summary>
    public abstract void TestCleanup();

    /// <summary>
    /// Exit the client cleanly. This should normally wait for the current
    /// call to complete, perform any additional cleanup tasks registered and
    /// then close the client. To immediately kill the client use <see cref="ForceKill"/>.
    /// </summary>
    public abstract void Exit();

    ~ClientBase()
    {
      Exit();
    }

    #region IDisposable Members

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

    #endregion
  }
}
