// Buyer.java
// Copyright (c) 1999 Wei Tao
// Author Wei Tao
// November 8, 1999

package JThread.examples.buyer;

import java.io.*;
import com.objectspace.lib.timer.*;
import com.objectspace.voyager.*;
import com.objectspace.voyager.agent.*;
import java.util.Vector;
import JThread.voyager.*;

/**
 * The negotiation agent travels between home and vender.
 *
 * @version 1.0
 * @author <A HREF="http://www.cs.utah.edu/~tao">Wei Tao</A>
 */

public class Buyer implements IBuyer, Serializable
{
    public int delivery = 10;
    boolean atHome;
    
    private Stopwatch _agent_runtime;
   // private Stopwatch _shutdown_time;
   // private Stopwatch _restart_time;
  
    public Buyer()
    {
        _agent_runtime = new Stopwatch();
    //    _shutdown_time = new Stopwatch();
    //    _restart_time = new Stopwatch();

        atHome = true;
        System.out.println( atHomeToString() + "Buyer constructed with target delivery " +
            delivery + " days" );
    }
        
    public void run( IVendor vendor, Vector orders ) throws MoveException
    {
        _agent_runtime.start();
       
        // move to vendor site 
        Migration.moveTo("//localhost:8000");
        atHome = false;
        System.out.println( atHomeToString() + "Buyer now at vendor" );
        
        boolean metPrice = getBids( vendor, orders, 0 );    
        if ( metPrice )
        {
            System.out.println( atHomeToString() + 
                "Was able to get delivery on some items by original delivery date" );
        }
        else
        {
            System.out.println( atHomeToString() + "Buyer forced to extend delivery date on all items" );
            
            // ==> return to home
            Migration.moveTo("//localhost:7000");
            atHome = true;
            System.out.println( atHomeToString() + "Buyer now at home" );            
        }
        System.out.println( atHomeToString() + "Deal closed at total price " + totalCost( orders ) );
        
        _agent_runtime.stop();
        System.out.println("agent total time = " + _agent_runtime.getTotalTime() + "ms");
  //      System.out.println("total shutdown time = " + _shutdown_time.getTotalTime() + "ms");
  //      System.out.println("total restart time = " + _restart_time.getTotalTime() + "ms");
    }
    
    private boolean getBids( IVendor vendor, Vector orders, int nextItem ) throws MoveException
    {   
        if ( nextItem >= orders.size() )
        {
            // have bids on all items; get go/no go from HQ
            
            // return to home
            Migration.moveTo("//localhost:7000");
            atHome = true;
            System.out.println( atHomeToString() + "Buyer now at home" );
            
            if ( meetsPrice( totalCost( orders ) ) )
            {
                System.out.println( atHomeToString() + 
                    "Deal closed at original delivery date " + delivery );
                return true;
            }
            else
            {
                System.out.println( atHomeToString() + "Price " + totalCost( orders )
                    + " too high at original delivery date "  + delivery );
                    
                // extend delivery time requirement
                delivery = newDelivery( delivery );
                System.out.println( atHomeToString() + 
                    "Negotiations resumed with extended delivery date " + delivery );
                
                // return to vendor
                Migration.moveTo("//localhost:8000");
                atHome = false;
                System.out.println( atHomeToString() + "Buyer back at vendor" );
                
                // resume negotiation
                return false;
            }
        }
        else
        {
            // get bid on next item
            Order order = (Order)orders.elementAt( nextItem );
            order = vendor.getBid( order, delivery );
            orders.setElementAt( order, nextItem );
            
            // get bids on remaining items
            boolean metPrice = getBids( vendor, orders, nextItem+1 );
            if ( !metPrice )
            {
                // original deal not closed; need to rebid current item with extended delivery date
                order = vendor.getBid( order, delivery );
                orders.setElementAt( order, nextItem );
            }
                
            System.out.println( atHomeToString() + "Buyer accepts " + order.count + " " + 
                order.item + " at " + order.cost + " with " + order.days + " delivery" );
                    
            if ( !meetsPrice( totalCost( orders ) ) )
            {
                // must rebid on higher priority items
                return false;
            }

            // otherwise, no need to extend delivery dates for higher priority items
                
            // return home if this was first time price was met
            if ( !atHome )
            {
                System.out.println( atHomeToString() + 
                    "Price target met; no need for further delivery extension" );
                // ==> code to return home goes here
                Migration.moveTo("//localhost:7000");
                atHome = true;
                System.out.println( atHomeToString() + "Buyer returns home" );
            }
            return true;
        }
    }
    
    private boolean meetsPrice( int price )
    {
        return price < 3800;
    }
      
    private int newDelivery( int days )
    {
        return days*2;
    }
            
    private int totalCost( Vector orders )
    {
        int cost = 0;
        int i;
        for (i = 0; i<orders.size(); i++ )
        {
            cost += ((Order)orders.elementAt( i )).cost;
        }
        return cost;
    }
    
    private String atHomeToString()
    {
        if ( atHome )
            return "[H] ";
        return "[V] ";
    }

  }
