/*
 *  bondFaultMonitorSearcher.java
 *    @contains It asks other agents to monitor "me".
       See README in this directory for detail.
 *    @author Kyungkoo Jun
 *    Bond group, CS, Purdue Univ.
 *    created on Nov 14, 2000
 *
 */

package bond.agent.FaultDetection;

import bond.core.*;
import java.util.*;

public class bondFaultMonitorSearcher
extends bondFaultDetectionExecutable
{

  boolean repaired;

  public bondFaultMonitorSearcher(bondFaultStatus fs, boolean repaired) {

    super(fs);
    this.repaired = repaired;
    go();
  }


  public void run() {
    run2();
    while (fs.amIorphan() && fs.getFaultFreeList().size() > 1) {
      //       try {
      // 	thread.sleep(bondFaultStatus.WAIT_TIME-25000);
      //       }
      //       catch (InterruptedException e) {
      //       }
      run2();    
    }
  }

  public void run2() {

    Vector temp = fs.getFaultFreeList();
    String dst = null;
    if (temp.size() == 0 || (temp.size() == 1 && ((String)temp.elementAt(0)).equals(fs.getMyID()))) {
      fs.setSearchingFlag(false);
      dir.unregister(this);
      return;
    }

    Vector v = new Vector();
    for (int i = 0; i < temp.size(); i++) {
      v.addElement(new Integer(bondFaultStatus.getIDnum((String)temp.elementAt(i))));
    }
     
    Integer mynum = new Integer(bondFaultStatus.getIDnum(fs.getMyID()));
    Object[] array = v.toArray();
    Arrays.sort(array);

    int k = Arrays.binarySearch(array, mynum);
    k--;
    if (k < 0)
      k = array.length-1;

    Integer value = (Integer)array[k];
    for (int i = 0; i < temp.size(); i++) {
      dst = (String)temp.elementAt(i);
      if (dst.startsWith("Agent"+value+"+"))
	break;
    }

    if (!dst.equals(fs.getMyID()) && !fs.isFaulty(dst)) {

      bondShadow bs =  bondFaultStatus.buildShadow(dst);
      bondMessage msg;
      if (repaired) {
	msg = new bondMessage("(tell :content testmejoin-msg)","FaultDetection");
      }
      else {
	msg = new bondMessage("(tell :content testme-msg)","FaultDetection");
      }
      msg.setParameter(":ID", fs.getMyID());

      if (repaired) {
	filelogger.log(fs.getMyID()+" askJoin");
      }
      else {
	filelogger.log(fs.getMyID()+" askMonitoring");
      }

      bondMessage rep = bs.ask(msg, this, bondFaultStatus.WAIT_TIME);
      bondFaultStatus.Log(fs.getMyID(), "send request >> "+dst, false);

      if (finish) {
	dir.unregister(this);
	return;
      }
      if (rep == null || rep.getSubprotocol() == null ||
	  !rep.getSubprotocol().equals("FaultDetection")) {
// 	if (fs.foundFaulty(dst)) {
// 	  fs.disseminateInfo(dst);
// 	}
      }
      else {
	if (rep.content.equals("i-will-monitor-you")) {

	  bondFaultStatus.Log(fs.getMyID(), "accepted <<"+(String)rep.getParameter(":ID"), false);

	  fs.setMonitoredBy((String)rep.getParameter(":ID"));
	  Hashtable ht = (Hashtable)rep.getParameter(":status");
	  if (ht != null)
	    fs.setNewStatus(ht);
	  fs.setSearchingFlag(false);
	  dir.unregister(this);
	  return;
	} else if (rep.content.equals("i-am-busy")) {

	  bondFaultStatus.Log(fs.getMyID(), "decliend << "+(String)rep.getParameter(":ID"), false);
	  Hashtable ht = (Hashtable)rep.getParameter(":status");
	  if (ht != null)
	    fs.setNewStatus(ht);
	}
      }
    }

    if (finish) {
      dir.unregister(this);
      return;
    }
    
  }
}

