/*
 * Copyright (c) 2007-2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.net4j.util.tests;

import org.eclipse.net4j.internal.util.test.TestExecuter;
import org.eclipse.net4j.tests.bundle.OM;
import org.eclipse.net4j.util.ReflectUtil;
import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.concurrent.TrackableTimerTask;
import org.eclipse.net4j.util.event.EventUtil;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.INotifier;
import org.eclipse.net4j.util.io.IORuntimeException;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.io.TMPUtil;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.OMPlatform;
import org.eclipse.net4j.util.om.log.FileLogHandler;
import org.eclipse.net4j.util.om.log.OMLogger;
import org.eclipse.net4j.util.om.log.OMLogger.Level;
import org.eclipse.net4j.util.om.log.PrintLogHandler;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.om.trace.PrintTraceHandler;

import org.junit.Assert;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import junit.framework.TestResult;

/**
 * @author Eike Stepper
 */
public abstract class AbstractOMTest extends TestCase
{
  public static final long DEFAULT_TIMEOUT = 15 * 1000;

  public static final long DEFAULT_TIMEOUT_EXPECTED = 3 * 1000;

  public static boolean EXTERNAL_LOG;

  public static boolean SUPPRESS_OUTPUT;

  private static final IListener DUMPER = new IListener()
  {
    public void notifyEvent(IEvent event)
    {
      IOUtil.OUT().println(event);
    }
  };

  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractOMTest.class);

  private static boolean consoleEnabled;

  private static String testName;

  private transient List<File> filesToDelete = new ArrayList<File>();

  private transient String codeLink;

  static
  {
    try
    {
      if (EXTERNAL_LOG)
      {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String prefix = AbstractOMTest.class.getName() + "-" + formatter.format(new Date()) + "-";
        File logFile = TMPUtil.createTempFile(prefix, ".log");

        OMPlatform.INSTANCE.addLogHandler(new FileLogHandler(logFile, OMLogger.Level.WARN)
        {
          @Override
          protected void writeLog(OMLogger logger, Level level, String msg, Throwable t) throws Throwable
          {
            super.writeLog(logger, level, "--> " + testName + "\n" + msg, t);
          }
        });

        IOUtil.ERR().println("Logging errors and warnings to " + logFile);
        IOUtil.ERR().println();
      }
    }
    catch (Throwable ex)
    {
      IOUtil.print(ex);
    }
  }

  protected AbstractOMTest()
  {
  }

  public String getCodeLink()
  {
    return codeLink;
  }

  public void determineCodeLink()
  {
    if (codeLink == null)
    {
      codeLink = determineCodeLink(getName());
      if (codeLink == null)
      {
        codeLink = determineCodeLink("doSetUp");
        if (codeLink == null)
        {
          codeLink = getClass().getName() + "." + getName() + "(" + getClass().getSimpleName() + ".java:1)";
        }
      }
    }
  }

  protected String determineCodeLink(String methodName)
  {
    String className = getClass().getName();
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    for (StackTraceElement frame : stackTrace)
    {
      if (frame.getClassName().equals(className) && frame.getMethodName().equals(methodName))
      {
        return frame.toString();
      }
    }

    return null;
  }

  protected boolean logSetUpAndTearDown()
  {
    return false;
  }

  @Override
  public void setUp() throws Exception
  {
    testName = getClass().getName() + "." + getName() + "()";
    codeLink = null;

    PrintTraceHandler.CONSOLE.setShortContext(true);
    OMPlatform.INSTANCE.addTraceHandler(PrintTraceHandler.CONSOLE);
    OMPlatform.INSTANCE.addLogHandler(PrintLogHandler.CONSOLE);
    enableConsole();

    if (!SUPPRESS_OUTPUT)
    {
      IOUtil.OUT().println("*******************************************************"); //$NON-NLS-1$
      Thread.yield();
      Thread.sleep(2L);
      IOUtil.ERR().println(this);
      Thread.yield();
      Thread.sleep(2L);
      IOUtil.OUT().println("*******************************************************"); //$NON-NLS-1$
    }

    if (!logSetUpAndTearDown())
    {
      disableConsole();
    }

    super.setUp();
    doSetUp();

    if (!SUPPRESS_OUTPUT && logSetUpAndTearDown())
    {
      IOUtil.OUT().println();
      IOUtil.OUT().println("------------------------ START ------------------------"); //$NON-NLS-1$
    }

    enableConsole();
  }

  @Override
  public void tearDown() throws Exception
  {
    if (logSetUpAndTearDown())
    {
      enableConsole();
    }
    else
    {
      disableConsole();
    }

    if (!SUPPRESS_OUTPUT && logSetUpAndTearDown())
    {
      IOUtil.OUT().println("------------------------- END -------------------------"); //$NON-NLS-1$
      IOUtil.OUT().println();
    }

    try
    {
      doTearDown();
    }
    catch (Exception ex)
    {
      IOUtil.print(ex);
    }

    try
    {
      super.tearDown();
    }
    catch (Exception ex)
    {
      IOUtil.print(ex);
    }

    try
    {
      TrackableTimerTask.logConstructionStackTraces(2 * DEFAULT_TIMEOUT);
    }
    catch (Exception ex)
    {
      IOUtil.print(ex);
    }

    try
    {
      clearReferences(getClass());
    }
    catch (Exception ex)
    {
      IOUtil.print(ex);
    }

    if (!SUPPRESS_OUTPUT)
    {
      IOUtil.OUT().println();
      IOUtil.OUT().println();
    }
  }

  protected void clearReferences(Class<?> c)
  {
    if (c != AbstractOMTest.class)
    {
      for (Field field : c.getDeclaredFields())
      {
        if (Modifier.isStatic(field.getModifiers()))
        {
          continue;
        }

        if (field.getType().isPrimitive())
        {
          continue;
        }

        ReflectUtil.setValue(field, this, null);
      }

      clearReferences(c.getSuperclass());
    }
  }

  @Override
  public void runBare() throws Throwable
  {
    TestExecuter.execute(this, new TestExecuter.Executable()
    {
      public void execute() throws Throwable
      {
        try
        {
          Throwable exception = null;

          try
          {
            setUp();

            // Don't call super.runBare() because it does not clean up after exceptions from setUp()
            runTest();
          }
          catch (Throwable running)
          {
            exception = running;
          }
          finally
          {
            try
            {
              tearDown();
            }
            catch (Throwable tearingDown)
            {
              if (exception == null)
              {
                exception = tearingDown;
              }
            }
          }

          if (exception != null)
          {
            throw exception;
          }
        }
        catch (SkipTestException ex)
        {
          OM.LOG.info("Skipped " + this); //$NON-NLS-1$
        }
        catch (Throwable t)
        {
          // AssertionFailedError assertionFailedError = getAssertionFailedError(t);
          // if (assertionFailedError != null)
          // {
          // t = assertionFailedError;
          // }

          if (!SUPPRESS_OUTPUT)
          {
            t.printStackTrace(IOUtil.OUT());
          }

          throw t;
        }
      }
    });
  }

  @Override
  public void run(TestResult result)
  {
    try
    {
      super.run(result);
    }
    catch (SkipTestException ex)
    {
      OM.LOG.info("Skipped " + this); //$NON-NLS-1$
    }
    catch (RuntimeException ex)
    {
      if (!SUPPRESS_OUTPUT)
      {
        ex.printStackTrace(IOUtil.OUT());
      }

      throw ex;
    }
    catch (Error err)
    {
      // AssertionFailedError assertionFailedError = getAssertionFailedError(err);
      // if (assertionFailedError != null)
      // {
      // err = assertionFailedError;
      // }

      if (!SUPPRESS_OUTPUT)
      {
        err.printStackTrace(IOUtil.OUT());
      }

      throw err;
    }
  }

  // private AssertionFailedError getAssertionFailedError(Throwable err)
  // {
  // if (err.getClass() == AssertionError.class)
  // {
  // // JUnit4 seems to throw java.lang.AssertionError, which the JUNit view displays as error rather than failure
  // AssertionFailedError replacementError = new AssertionFailedError(err.getMessage());
  // replacementError.initCause(err);
  // return replacementError;
  // }
  //
  // if (err instanceof AssertionFailedError)
  // {
  // return (AssertionFailedError)err;
  // }
  //
  // return null;
  // }

  protected void enableConsole()
  {
    if (!SUPPRESS_OUTPUT)
    {
      OMPlatform.INSTANCE.setDebugging(true);
      consoleEnabled = true;
    }
  }

  protected void disableConsole()
  {
    if (!SUPPRESS_OUTPUT)
    {
      consoleEnabled = false;
      OMPlatform.INSTANCE.setDebugging(false);
      // OMPlatform.INSTANCE.removeTraceHandler(PrintTraceHandler.CONSOLE);
      // OMPlatform.INSTANCE.removeLogHandler(PrintLogHandler.CONSOLE);
    }
  }

  protected void doSetUp() throws Exception
  {
  }

  protected void doTearDown() throws Exception
  {
    deleteFiles();
  }

  public synchronized void deleteFiles()
  {
    for (File file : filesToDelete)
    {
      IOUtil.delete(file);
    }

    filesToDelete.clear();
  }

  public synchronized void addFileToDelete(File file)
  {
    filesToDelete.add(file);
  }

  public File createTempFolder() throws IORuntimeException
  {
    File folder = TMPUtil.createTempFolder();
    addFileToDelete(folder);
    return folder;
  }

  public File createTempFolder(String prefix) throws IORuntimeException
  {
    File folder = TMPUtil.createTempFolder(prefix);
    addFileToDelete(folder);
    return folder;
  }

  public File createTempFolder(String prefix, String suffix) throws IORuntimeException
  {
    File folder = TMPUtil.createTempFolder(prefix, suffix);
    addFileToDelete(folder);
    return folder;
  }

  public File createTempFolder(String prefix, String suffix, File directory) throws IORuntimeException
  {
    File folder = TMPUtil.createTempFile(prefix, suffix, directory);
    addFileToDelete(folder);
    return folder;
  }

  public File createTempFile() throws IORuntimeException
  {
    File file = TMPUtil.createTempFile();
    addFileToDelete(file);
    return file;
  }

  public File createTempFile(String prefix) throws IORuntimeException
  {
    File file = TMPUtil.createTempFile(prefix);
    addFileToDelete(file);
    return file;
  }

  public File createTempFile(String prefix, String suffix) throws IORuntimeException
  {
    File file = TMPUtil.createTempFile(prefix, suffix);
    addFileToDelete(file);
    return file;
  }

  public File createTempFile(String prefix, String suffix, File directory) throws IORuntimeException
  {
    File file = TMPUtil.createTempFile(prefix, suffix, directory);
    addFileToDelete(file);
    return file;
  }

  @Override
  public String toString()
  {
    return getClass().getSimpleName() + "." + getName();
  }

  public static AbstractOMTest getCurrrentTest()
  {
    return (AbstractOMTest)TestExecuter.getValue();
  }

  /**
   * @deprecated Use assertEquals(message, true, ...)
   */
  @Deprecated
  public static void assertTrue(String message, boolean condition)
  {
    throw new UnsupportedOperationException("Use assertEquals(message, true, ...)");
  }

  /**
   * @deprecated Use assertEquals(true, ...)
   */
  @Deprecated
  public static void assertTrue(boolean condition)
  {
    throw new UnsupportedOperationException("Use assertEquals(true, ...)");
  }

  /**
   * @deprecated Use assertEquals(message, false, ...)
   */
  @Deprecated
  public static void assertFalse(String message, boolean condition)
  {
    throw new UnsupportedOperationException("Use assertEquals(message, false, ...)");
  }

  /**
   * @deprecated Use assertEquals(false, ...)
   */
  @Deprecated
  public static void assertFalse(boolean condition)
  {
    throw new UnsupportedOperationException("Use assertEquals(false, ...)");
  }

  public static void assertEquals(Object[] expected, Object[] actual)
  {
    if (!Arrays.deepEquals(expected, actual))
    {
      throw new AssertionFailedError(
          "expected:" + Arrays.deepToString(expected) + " but was:" + Arrays.deepToString(actual));
    }
  }

  public static void assertEquals(Object expected, Object actual)
  {
    if (actual == expected)
    {
      return;
    }

    try
    {
      Assert.assertEquals(expected, actual);
    }
    catch (AssertionError ex)
    {
      AssertionFailedError error = new AssertionFailedError(ex.getMessage());
      error.initCause(ex);
      throw error;
    }
  }

  public static void assertEquals(String message, Object expected, Object actual)
  {
    if (expected == null && actual == null)
    {
      return;
    }

    if (expected != null && expected.equals(actual))
    {
      return;
    }

    // IMPORTANT: Give possible CDOLegacyWrapper a chance for actual, too
    if (actual != null && actual.equals(expected))
    {
      return;
    }

    failNotEquals(message, expected, actual);
  }

  public static void sleep(long millis)
  {
    msg("Sleeping " + millis);
    ConcurrencyUtil.sleep(millis);
  }

  public static void assertInstanceOf(Class<?> expected, Object object)
  {
    assertEquals("Not an instance of " + expected + ": " + object.getClass().getName(), true,
        expected.isInstance(object));
  }

  public static void assertNotInstanceOf(Class<?> expected, Object object)
  {
    assertEquals("An instance of " + expected + ": " + object.getClass().getName(), false, expected.isInstance(object));
  }

  public static void assertActive(Object object) throws InterruptedException
  {
    final LatchTimeOuter timeOuter = new LatchTimeOuter();
    IListener listener = new LifecycleEventAdapter()
    {
      @Override
      protected void onActivated(ILifecycle lifecycle)
      {
        timeOuter.countDown();
      }
    };

    EventUtil.addListener(object, listener);

    try
    {
      if (LifecycleUtil.isActive(object))
      {
        timeOuter.countDown();
      }

      timeOuter.assertNoTimeOut();
    }
    finally
    {
      EventUtil.removeListener(object, listener);
    }
  }

  public static void assertInactive(Object object) throws InterruptedException
  {
    final LatchTimeOuter timeOuter = new LatchTimeOuter();
    IListener listener = new LifecycleEventAdapter()
    {
      @Override
      protected void onDeactivated(ILifecycle lifecycle)
      {
        timeOuter.countDown();
      }
    };

    EventUtil.addListener(object, listener);

    try
    {
      if (!LifecycleUtil.isActive(object))
      {
        timeOuter.countDown();
      }

      timeOuter.assertNoTimeOut();
    }
    finally
    {
      EventUtil.removeListener(object, listener);
    }
  }

  public static void assertSimilar(double expected, double actual, int precision)
  {
    final double factor = 10 * precision;
    if (Math.round(expected * factor) != Math.round(actual * factor))
    {
      assertEquals(expected, actual);
    }
  }

  public static void assertSimilar(float expected, float actual, int precision)
  {
    final float factor = 10 * precision;
    if (Math.round(expected * factor) != Math.round(actual * factor))
    {
      assertEquals(expected, actual);
    }
  }

  public static void msg(Object m)
  {
    if (!SUPPRESS_OUTPUT)
    {
      if (consoleEnabled && TRACER.isEnabled())
      {
        TRACER.trace("--> " + m); //$NON-NLS-1$
      }
    }
  }

  public static void dumpEvents(Object notifier)
  {
    dumpEvents(notifier, true);
  }

  public static void dumpEvents(Object notifier, boolean on)
  {
    if (notifier instanceof INotifier)
    {
      INotifier iNotifier = (INotifier)notifier;
      IListener[] listeners = iNotifier.getListeners();

      boolean wasOn = false;
      for (int i = 0; i < listeners.length; i++)
      {
        if (listeners[i] == DUMPER)
        {
          wasOn = true;
          break;
        }
      }

      if (on && !wasOn)
      {
        iNotifier.addListener(DUMPER);
      }
      else if (!on && wasOn)
      {
        iNotifier.removeListener(DUMPER);
      }
    }
  }

  public static void skipTest(boolean skip)
  {
    if (skip)
    {
      throw new SkipTestException();
    }
  }

  public static void skipTest()
  {
    skipTest(true);
  }

  /**
   * @author Eike Stepper
   */
  private static final class SkipTestException extends RuntimeException
  {
    private static final long serialVersionUID = 1L;
  }

  /**
   * @author Eike Stepper
   */
  public static class AsyncResult<T>
  {
    private volatile T value;

    private CountDownLatch latch = new CountDownLatch(1);

    public AsyncResult()
    {
    }

    public void setValue(T value)
    {
      this.value = value;
      latch.countDown();
    }

    public T getValue(long timeout) throws Exception
    {
      if (!latch.await(timeout, TimeUnit.MILLISECONDS))
      {
        throw new TimeoutException("Result value not available after " + timeout + " milli seconds");
      }

      return value;
    }

    public T getValue() throws Exception
    {
      return getValue(DEFAULT_TIMEOUT);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static interface ITimeOuter
  {
    public boolean timedOut(long timeoutMillis) throws InterruptedException;
  }

  /**
   * @author Eike Stepper
   */
  public static abstract class TimeOuter implements ITimeOuter
  {
    public boolean timedOut() throws InterruptedException
    {
      return timedOut(DEFAULT_TIMEOUT);
    }

    public void assertTimeOut(long timeoutMillis) throws InterruptedException
    {
      assertEquals("Timeout expected", true, timedOut(timeoutMillis));
    }

    public void assertTimeOut() throws InterruptedException
    {
      assertTimeOut(DEFAULT_TIMEOUT_EXPECTED);
    }

    public void assertNoTimeOut(long timeoutMillis) throws InterruptedException
    {
      assertEquals("Timeout after " + timeoutMillis + " millis", false, timedOut(timeoutMillis));
    }

    public void assertNoTimeOut() throws InterruptedException
    {
      assertNoTimeOut(DEFAULT_TIMEOUT);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static abstract class PollingTimeOuter extends TimeOuter
  {
    public static final long DEFAULT_SLEEP_MILLIS = 1;

    private long sleepMillis = DEFAULT_SLEEP_MILLIS;

    public PollingTimeOuter(long sleepMillis)
    {
      this.sleepMillis = sleepMillis;
    }

    public PollingTimeOuter()
    {
    }

    public boolean timedOut(long timeoutMillis) throws InterruptedException
    {
      int retries = (int)Math.round(timeoutMillis / sleepMillis + .5d);
      for (int i = 0; i < retries; i++)
      {
        if (successful())
        {
          return false;
        }

        sleep(sleepMillis);
      }

      return true;
    }

    protected abstract boolean successful();
  }

  /**
   * @author Eike Stepper
   */
  public static class LockTimeOuter extends TimeOuter
  {
    private Lock lock;

    public LockTimeOuter(Lock lock)
    {
      this.lock = lock;
    }

    public Lock getLock()
    {
      return lock;
    }

    public boolean timedOut(long timeoutMillis) throws InterruptedException
    {
      Condition condition = lock.newCondition();
      return !condition.await(timeoutMillis, TimeUnit.MILLISECONDS);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static class LatchTimeOuter extends TimeOuter
  {
    private CountDownLatch latch;

    public LatchTimeOuter(CountDownLatch latch)
    {
      this.latch = latch;
    }

    public LatchTimeOuter(int count)
    {
      this(new CountDownLatch(count));
    }

    public LatchTimeOuter()
    {
      this(1);
    }

    public CountDownLatch getLatch()
    {
      return latch;
    }

    public long getCount()
    {
      return latch.getCount();
    }

    public void countDown()
    {
      latch.countDown();
    }

    public void countDown(int n)
    {
      for (int i = 0; i < n; i++)
      {
        countDown();
      }
    }

    public boolean timedOut(long timeoutMillis) throws InterruptedException
    {
      return !latch.await(timeoutMillis, TimeUnit.MILLISECONDS);
    }
  }
}
