/*public int numTickGroups()
 {
 	return ticks.size();
 }*/
 public String[][] threadInfo() {
   ArrayList<String[]> V = new ArrayList();
   for (Iterator<CMLibrary> e = CMLib.libraries(); e.hasNext(); ) {
     CMLibrary lib = e.next();
     SupportThread thread = lib.getSupportThread();
     if (thread != null) {
       String[] S = new String[3];
       S[0] = thread.getName();
       S[1] = CMLib.english().returnTime(thread.milliTotal, thread.tickTotal);
       S[2] = thread.status;
       V.add(S);
     }
   }
   return V.toArray(new String[V.size()][]);
 }
  /*
  	public String tickInfo(String which)
  	{
  		int grpstart=-1;
  		for(int i=0;i<which.length();i++)
  			if(Character.isDigit(which.charAt(i)))
  			{
  				grpstart=i;
  				break;
  			}
  		if(which.equalsIgnoreCase("tickGroupSize"))
  			return ""+ticks.size();
  		else if(which.toLowerCase().startsWith("tickerssize"))
  		{
  			if(grpstart<0) return"";
  			int group=CMath.s_int(which.substring(grpstart));
  			if((group>=0)&&(group<ticks.size()))
  				return ""+((Tick)ticks.get(group)).numTickers();
  			return "";
  		}
  		int group=-1;
  		int client=-1;
  		int clistart=which.indexOf("-");
  		if((grpstart>=0)&&(clistart>grpstart))
  		{
  			group=CMath.s_int(which.substring(grpstart,clistart));
  			client=CMath.s_int(which.substring(clistart+1));
  		}

  		if((group<0)||(client<0)||(group>=ticks.size())) return "";
  		Tick almostTock=(Tick)ticks.get(group);

  		if(client>=almostTock.numTickers()) return "";
  		TockClient C=null;
  		almostTock.fetchTickerByIndex(client);
  		if(C==null) return "";

  		if(which.toLowerCase().startsWith("tickername"))
  		{
  			Tickable E=C.clientObject;
  			if(E instanceof Room)
  				return E.ID()+((Room)E).saveNum();
  			if(E!=null) return E.ID();
  			return "!NULL!";
  		}
  		else
  		if(which.toLowerCase().startsWith("tickerstatus"))
  			return ((C.clientObject==null)?"":(""+C.clientObject.getTickStatus()));
  		return "";
  	}
  */
  public boolean shutdown() {
    // int numTicks=tickGroup.size();
    /*while(ticks.size()>0)
    {
    	//Log.sysOut("ServiceEngine","Shutting down all tick "+which+"/"+numTicks+"...");
    	Tick tock=ticks.first();
    	if(tock!=null)
    	{
    		CMProps.Strings.MUDSTATUS.setProperty("Shutting down...shutting down Service Engine: killing Tick#" + tock.tickObjectCounter+": "+tock.getStatus());
    		tock.shutdown();
    	}
    	try{Thread.sleep(100);}catch(Exception e){}
    }*/
    while (areas.size() > 0) {
      TickArea tock = areas.first();
      if (tock != null) {
        CMProps.Strings.MUDSTATUS.setProperty(
            "Shutting down...shutting down Service Engine: killing Area#"
                + tock.tickObjectCounter
                + ": "
                + tock.clientObject.getTickStatus());
        tock.shutdown();
      }
      try {
        Thread.sleep(100);
      } catch (Exception e) {
      }
    }
    CMProps.Strings.MUDSTATUS.setProperty(
        "Shutting down...shutting down Service Engine: " + ID() + ": thread shutdown");
    thread.shutdown();
    Log.sysOut("ServiceEngine", "Shutdown complete.");
    return true;
  }
 public boolean activate() {
   if (thread == null)
     thread =
         new SupportThread(
             "THThreads",
             MudHost.TIME_UTILTHREAD_SLEEP,
             this,
             CMSecurity.isDebugging("UTILITHREAD"));
   if (!thread.started) thread.start();
   mainTime.start();
   /* if(exitThread==null)
   {
   	exitThread=
   	exitThread.start();
   } */
   return true;
 }
  /*
  	public void insertOrderDeathInOrder(DVector DV, long lastStart, String msg, Tick tock)
  	{
  		if(DV.size()>0)
  		for(int i=0;i<DV.size();i++)
  		{
  			if(((Long)DV.elementAt(i,0)).longValue()>lastStart)
  			{
  				DV.insertRowAt(i,Long.valueOf(lastStart),msg,tock);
  				return;
  			}
  		}
  		DV.addRow(Long.valueOf(lastStart),msg,tock);
  	}
  */
  public void checkHealth() {
    long lastDateTime = System.currentTimeMillis() - (5 * CoffeeTime.MILI_MINUTE);
    // long longerDateTime=System.currentTimeMillis()-(120*CoffeeTime.MILI_MINUTE);
    // thread.status("checking");

    ArrayList<TickArea> orderedDeaths = new ArrayList();
    thread.status("checking tick groups.");
    /*for(Iterator<Tick> e=ticks.iterator();e.hasNext();)
    {
    	Tick almostTock=e.next();
    	if((almostTock.awake)
    	&&(almostTock.lastStop<lastDateTime))
    	{
    		//insertOrderDeathInOrder(orderedDeaths,0,"LOCKED GROUP "+almostTock.tickObjectCounter+"! No further information.",almostTock);
    		delTickGroup(almostTock);
    		orderedDeaths.add(almostTock);	//"LOCKED GROUP "+almostTock.tickObjectCounter+"! No further information."
    		// no isDEBUGGING check -- just always let her rip.
    		Log.errOut(thread.getName(),"LOCKED TICK GROUP "+almostTock.tickObjectCounter);
    		thread.debugDumpStack(almostTock);
    	}
    }
    if(orderedDeaths.size()>0)
    {
    	thread.status("killing tick groups.");
    	for(int x=0;x<orderedDeaths.size();x++)
    	{
    		Tick almostTock=orderedDeaths.get(x);
    		ArrayList<TickActer> objs=new ArrayList();
    		try{
    			for(TickActer E : almostTock.tickers())
    				objs.add(E);
    		}catch(NoSuchElementException e){}
    		almostTock.shutdown();
    		//if(CMLib.threads() instanceof ServiceEngine)
    		//	((ServiceEngine)CMLib.threads()).
    		//delTickGroup(almostTock);
    		for(int i=0;i<objs.size();i++)
    			startTickDown(objs.get(i));
    	}
    	orderedDeaths.clear();
    }*/
    thread.status("checking areas.");
    for (Iterator<TickArea> e = areas.iterator(); e.hasNext(); ) {
      TickArea almostTock = e.next();
      if ((almostTock.awake) && (almostTock.lastStop < lastDateTime)) {
        delArea(almostTock);
        // orderedDeaths.add(almostTock);	//"LOCKED GROUP "+almostTock.tickObjectCounter+"! No
        // further information."
        almostTock.shutdown();
        Log.errOut(thread.getName(), "LOCKED TICK GROUP " + almostTock.tickObjectCounter);
        thread.debugDumpStack(almostTock);
        startArea(almostTock.clientObject, almostTock.TICK_TIME);
      }
    }
    /*
    		thread.status("Checking mud threads");
    		for(int m=0;m<CMLib.hosts().size();m++)
    		{
    			Vector badThreads=((MudHost)CMLib.hosts().elementAt(m)).getOverdueThreads();
    			if(badThreads.size()>0)
    			{
    				for(int b=0;b<badThreads.size();b++)
    				{
    					Thread T=(Thread)badThreads.elementAt(b);
    					String threadName=T.getName();
    					if(T instanceof Tickable)
    						threadName=((Tickable)T).ID()+" ("+((Tickable)T).ID()+"): "+((Tickable)T).getTickStatus();
    					thread.status("Killing "+threadName);
    					Log.errOut("Killing stray thread: "+threadName);
    					CMLib.killThread(T,100,1);
    				}
    			}
    		}
    		thread.status("Done checking threads");
    */
  }