package basics.profiler;

import java.util.Iterator;
import java.util.Vector;
import basics.collections.QueueRevolving;
import basics.utl.SysUtl;

public class AppWatcher
{
private AppWatcher()
{
}

static Vector<AppHistoryListener> listeners          = new Vector<AppHistoryListener>();
private static final AppWatcher   watcher            = new AppWatcher();
QueueRevolving<String>            mi                 = null;
static final int                  SIZE               = 5;
boolean                           on                 = false;
Thread                            thread             = null;
static final long                 INITIALSLEEPTIME   = 150;
static final long                 MAXSLEEPTIME       = 1500;
static final long                 INCREMENTSLEEPTIME = 0;
static final long                 SHOWEVERY          = 10;
static long                       sleeptime          = INITIALSLEEPTIME;
static long                       counter            = 0;

public static synchronized void addListener(AppHistoryListener listener)
{
   if(listener != null)
      listeners.add(listener);
}

private static synchronized void notifyListeners(String t)
{
   for(Iterator<AppHistoryListener> iter = listeners.iterator(); iter.hasNext();)
      iter.next().appHistoryEvent(t);
}

public static synchronized void exit()
{
   if(watcher.mi == null)
      return;
   watcher.on = false;
   counter = 0;
   try
   {
      watcher.thread.join();
   }
   catch(InterruptedException e)
   {
   }
   watcher.mi = null;
}

public static synchronized void step(String id)
{
   if(NoWatch.contains(id))
   {
      // OsUtl.trace("----- nowatch --: " + id );
      return;
   }
   // OsUtl.trace("----- WATCH --: " + id );
   start();
   watcher.mi.put(id);
}

private static synchronized void start()
{
   if(watcher.mi != null)
      return;
   watcher.mi = new QueueRevolving<String>(SIZE);
   watcher.on = true;
   Runnable m = new Runnable()
   {
      int unchanged = 0;

      public void run()
      {
         String lastChain = "";
         while(watcher.on)
         {
            // String currId = watcher.mi.last();
            String currentChain = watcher.mi.toString();
            if(!lastChain.equals(currentChain))
            {
               lastChain = currentChain;
               unchanged = 0;
            }
            else
               if(++unchanged % 3 == 0 && sleeptime < MAXSLEEPTIME)
                  sleeptime += INCREMENTSLEEPTIME;
            if(counter % SHOWEVERY == 0)
            {
               // StringBuilder s = new StringBuilder();
               // s.append(Chrono.currentTime());
               // s.append(" ");
               // s.append(currentChain);
               // s.append(" ..");
               // String est = Profiler.reportEstimatedTime(currId);
               // if (!Empty.is(est)) {
               // // s.append(currId);
               // s.append(":");
               // s.append(est);
               // }
               if(listeners.size() == 0)
                  SysUtl.println(currentChain);
               else
                  notifyListeners(currentChain);
            }
            counter++;
            try
            {
               Thread.sleep(sleeptime);
            }
            catch(InterruptedException e)
            {
            }
         }
      }
   };
   watcher.thread = new Thread(m);
   watcher.thread.setDaemon(true);
   watcher.thread.start();
}
}
