package basics.testing;

import java.io.File;
import java.io.PrintStream;
import basics.profiler.MemoryInfo;
import basics.utl.SUtl;

public class Test
{
public static final String LOGFILE      = "test.log";
static boolean             abortOnError = false;
static PrintStream         logger       = null;
static PrintStream         sout         = null;
static PrintStream         serr         = null;
static PrintStream         utf8printer  = null;
static MemoryInfo          memory       = new MemoryInfo();

static void redirectOutput()
{
   try
   {
      logger = new PrintStream(new File(LOGFILE), "UTF-8");
      utf8printer = new PrintStream(System.out, true, "UTF-8");
      sout = System.out;
      serr = System.err;
      System.setErr(logger);
      System.setOut(logger);
   }
   catch(Exception e)
   {
   }
}

static void endRedirectOutput()
{
   try
   {
      System.setErr(serr);
      System.setOut(sout);
      logger.flush();
      logger.close();
   }
   catch(Exception e)
   {
   }
}

/**
 * @return false if assertion failed or an exception occurred when evaluating the expression
 */
public static boolean assertTrue(boolean expression, String msg)
{
   try
   {
      if(!expression)
         fail(msg);
      else
         return true;
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
   }
   return false;
}

/**
 * @return false if assertion failed or an exception occurred when evaluating the expression
 */
public static boolean assertFalse(boolean expression, String msg)
{
   try
   {
      if(expression)
         fail(msg);
      else
         return true;
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
   }
   return false;
}

/**
 * @return false if assertion failed or an exception occurred when evaluating the expression
 */
public static boolean assertEqualsTrue(Object testedValue, Object referenceValue, String msg)
{
   try
   {
      if(testedValue == null && referenceValue != null)
      {
         fail(msg);
         return false;
      }
      if(referenceValue instanceof String)
      {
         if(!referenceValue.equals(testedValue))
         {
            fail(msg);
            return false;
         }
      }
      else
         if(referenceValue instanceof Number)
         {
            if(((Double)referenceValue).compareTo((Double)testedValue) != 0)
            {
               fail(msg);
               return false;
            }
         }
         else
            if(!referenceValue.toString().equals(testedValue.toString()))
            {
               fail(msg);
               return false;
            }
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
      return false;
   }
   return true;
}

public static boolean assertEqualsFalse(Object testedValue, Object referenceValue, String msg)
{
   try
   {
      if(testedValue == null && referenceValue == null)
      {
         fail(msg);
         return false;
      }
      if(referenceValue instanceof String)
      {
         if(referenceValue.equals(testedValue))
         {
            fail(msg);
            return false;
         }
      }
      else
         if(referenceValue instanceof Number)
         {
            if(((Double)referenceValue).compareTo((Double)testedValue) == 0)
            {
               fail(msg);
               return false;
            }
         }
         else
            if(referenceValue.toString().equals(testedValue.toString()))
            {
               fail(msg);
               return false;
            }
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
      return false;
   }
   return true;
}

public static boolean assertNotNull(Object expression, String msg)
{
   try
   {
      if(expression == null)
         fail(msg);
      else
         return true;
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
   }
   return false;
}

public static boolean assertNull(Object expression, String msg)
{
   try
   {
      if(expression != null)
         fail(msg);
      else
         return true;
   }
   catch(Throwable t)
   {
      fail(t.getMessage());
   }
   return false;
}

/**
 * Handle an exception (as a failure).
 * The exception would be caught during test,
 * printer redirection is set off during printstacktrace.
 * @param t
 */
public static void handleAsFailure(Throwable t)
{
   logger.flush();
   System.setOut(utf8printer);
   System.setErr(utf8printer);
   t.printStackTrace();
   System.setOut(logger);
   System.setErr(logger);
   if(abortOnError)
   {
      printout("TEST(s) ABORTED.");
      endRedirectOutput();
      System.exit(-1);
   }
}

public static void handleAsFeature(Throwable t)
{
}

public static void handleAsFeature(Throwable t, String msg)
{
   if(t == null)
   {
      printout(msg);
      if(abortOnError)
      {
         printout("TEST(s) ABORTED.");
         endRedirectOutput();
         System.exit(-1);
      }
   }
}

static void fail(String msg)
{
   printout(msg);
   if(abortOnError)
   {
      printout("TEST(s) ABORTED.");
      endRedirectOutput();
      System.exit(-1);
   }
}

public static void printout(String msg)
{
   if(logger != null)
      logger.flush();
   if(utf8printer != null)
      System.setOut(utf8printer);
   System.out.println(msg);
   if(logger != null)
      System.setOut(logger);
}

public static void printout(String msg, Object...obj)
{
   //   logger.flush();
   //   System.setOut(utf8printer);
   //   System.out.println(SUtl.sprint(msg, obj));
   //   System.setOut(logger);
   printout(SUtl.sprint(msg, obj));
}

public static void unittest()
{
}
}
