package org.bucksch.zeipis.all;
import java.util.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Util
{
  //////////////////////////////////////////////////
  // Collections
  //////////////////////////////////////////////////

  /**
   * http://www-128.ibm.com/developerworks/java/library/j-jtp02216.html
   */
  public static <E> Collection<E> newCollection()
  {
    return new Vector<E>();
  }
  public static <E> Vector<E> newVector()
  {
    return new Vector<E>();
  }
  public static <E> Set<E> newSet()
  {
    return new HashSet<E>();
  }
  public static <K,V> Map<K,V> newMap()
  {
    return new HashMap<K,V>();
  }

  public static <E> Vector<E> sort(Vector<E> org, Comparator<E> comparator)
  {
    Vector<E> result = newVector();
    result.addAll(org);
    for (int i1 = 0; i1 < result.size(); i1++)
    {
      E e1 = result.elementAt(i1);
      for (int i2 = i1 + 1; i2 < result.size(); i2++)
      {
        E e2 = result.elementAt(i2);
        if (comparator.compare(e1, e2) > 0)
        {
          result.set(i1, e2);
          result.set(i2, e1);
          e1 = e2;
        }
      }
    } 
    return result;
  }

  /**
   * @param <E> If not a string, it will be toString()ed the same way as |String + <E>| does.
   * @param coll
   * @param delimiter   e.g. ", "
   * @return e.g. "5, 6, 7"
   */
  public static <E> String joinToStrin(Collection<E> coll, String delimiter)
  {
    if (coll == null)
      return "";
    String result = "";
    for (Iterator<E> i = coll.iterator(); i.hasNext(); )
    {
      result += i.next();
      if (i.hasNext())
        result += delimiter;
    }
    return result;
  }

  /**
   * For ABCD returns ABCD, ABC, AB, BCD, BC, CD, in this order.
   * @return Every possible combination. Do not modify the List<E>s.
   */
  static public <E> Vector<List<E>> everyCombination(Vector<E> set)
  {
    Vector<List<E>> result = Util.newVector();
    // first items
    for (int i1 = 0; i1 < set.size(); i1++)
      // other items
      for (int i2 = set.size(); i2 > i1; i2--)
        result.add(set.subList(i1, i2));
    return result;
  }


  //////////////////////////////////////////////////
  // Error handling and logging
  //////////////////////////////////////////////////

  static public void debug(String msg)
  {
    System.out.println(currentTime() + " " + msg);
  }
  static public void warning(String msg)
  {
    System.err.println(currentTime() + " Warning: " + msg);
  }
  static public void error(Exception e)
  {
    System.err.println(currentTime() + " ERROR: " + e.getMessage());
    e.printStackTrace();
  }
  static public void error(String msg, Exception e)
  {
    System.out.println(currentTime() + " ERROR: " + msg + ": " + e.getMessage());
    e.printStackTrace();
  }
  static protected DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  static protected String currentTime()
  {
    return dateformat.format(new Date());
  }

  

  //////////////////////////////////////////////////
  // Various
  //////////////////////////////////////////////////

  static public String thisHostname()
  {
    if (myHost != null)
      return myHost;

    try {
      //byte[] ipAddr = InetAddress.getLocalHost().getAddress(); // IP Address
      String host = InetAddress.getLocalHost().getHostName();
      if (host.length() == 0 || host.equals("localhost"))
        throw new UnknownHostException(host);
      myHost = host;
      return myHost;
    } catch (UnknownHostException e) {
      throw new RuntimeException("Need hostname properly set up");
    }
  }
  static protected String myHost = null; // caching
  static public boolean isThisHost(String hostname)
  {
    return sameHost(thisHostname(), hostname);
  }
  static public boolean sameHost(String hostname1, String hostname2)
  {
    return hostname1.equals(hostname2);
  }

  /**
   * @return e.getLocalizedMessage() and that of all causes.
   */
  static public String getFullExceptionMessage(Exception e)
  {
    String result = e.getLocalizedMessage();
    Throwable cause = e;
    while ((cause = cause.getCause()) != null)
      result += ", because " + cause.getLocalizedMessage();
    return result;
  }
  static public String getStackTrace(Exception e)
  {
    // TODO
    return "";
  }
}
