// Buyer.java
// Copyright (c) 1999 Wei Tao
// Author Wei Tao
// November 8, 1999

package JThread.examples.agent;

import java.io.*;
import java.util.Vector;
import JThread.socket.*;

/**
 * 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 extends MobileThread
{
    private transient Vendor _vendor;
    
    public int delivery = 10;
    boolean atHome;
    Vector _orders;
      
    public Buyer(Vector orders)
    {
        atHome = true;
        _orders = orders;
        System.out.println( atHomeToString() + "Buyer constructed with target delivery " +
            delivery + " days" );
    }
        
    public void run() 
    {
        long start = System.currentTimeMillis();
        try {
//        for(int i = 0; i < 50; i++) {
            // move to vendor site 
            MigrationManager.moveTo("localhost:8000");
            atHome = false;
            System.out.println( atHomeToString() + "Buyer now at vendor" );
        
            boolean metPrice = getBids( _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
                MigrationManager.moveTo("localhost:7000");
                atHome = true;
                System.out.println( atHomeToString() + "Buyer now at home" );            
            }
            System.out.println( atHomeToString() + "Deal closed at total price " + totalCost( _orders ) );
   //     } 
        } catch(Exception e) { }

        long end = System.currentTimeMillis();
        System.out.println("total time = " + (end-start));
    }
    
    private boolean getBids( Vector orders, int nextItem ) throws MoveException
    {   
        if ( nextItem >= orders.size() )
        {
            // have bids on all items; get go/no go from HQ
            //System.out.println( atHomeToString() + "Have bids on all items, going back home");
            // return to home
            MigrationManager.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
                MigrationManager.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)Server.lookup("vendor")).getBid( order, delivery );
            orders.setElementAt( order, nextItem );
            
            // get bids on remaining items
            boolean metPrice = getBids( orders, nextItem+1 );
            if ( !metPrice )
            {
                // original deal not closed; need to rebid current item with extended delivery date
                order = ((Vendor)Server.lookup("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
                MigrationManager.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] ";
    }

  }
