

import madkit.kernel.*;
import madkit.lib.messages.*;
import madkit.kernel.GroupIdentifier;
import madkit.kernel.AgentAddress;
import java.io.*;
import java.io.Serializable;
import java.util.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


/**
 * Une classe représentant le comportement de l'agent Vendeur
 * 
 * @author Vincent Delord & Alexandre Lanoix
 * @version 1
 * @see madkit.kernel.Agent
 */


public class Vendeur extends Agent {
    
    
    public class VendeurGUI extends JPanel implements ItemListener, KeyListener, ActionListener{

	String poissonRecorded="saumon";
	
	JButton ok;
	JLabel monNom;
	JTextField nom;
	
	JLabel monPrix;
	JTextField prix;
	JLabel euros;
	
	JLabel monPoisson;
	JComboBox poisson;
	
	
	public VendeurGUI (Agent a) {
	    setSize(160,160);
	    setVisible(true);
	    GridLayout layout = new GridLayout(2,1);

	    // partie supérieure de l'interface : identité du vendeur
	    JPanel panel = new JPanel();
	    GridLayout grid = new GridLayout(4,1);
	    panel.setLayout(grid);

	    JPanel panel0 = new JPanel();
	    FlowLayout layout0 = new FlowLayout(FlowLayout.LEFT);
	    monNom = new JLabel ("Nom :",JLabel.RIGHT);
	    nom= new JTextField(12);
	    nom.addKeyListener(this);
	    panel0.add(monNom);
	    panel0.add(nom);
	    panel0.setLayout(layout0);
	    panel.add(panel0);
	    this.add(panel);

	    // partie mediane de l'interface : prix initial du poisson
	    JPanel panel1 = new JPanel();
	    FlowLayout layout1 = new FlowLayout(FlowLayout.LEFT);
	    monPrix = new JLabel ("Prix du poisson :",JLabel.RIGHT);
	    prix= new JTextField(5);
	    prix.addKeyListener(this);
	    euros = new JLabel("euros", JLabel.LEFT);
	    panel1.add(monPrix);
	    panel1.add(prix);
	    panel1.add(euros);
	    panel1.setLayout(layout1);
	    panel.add(panel1);
	    this.add(panel);
	    
	    //partie inférieure de l'interface : poisson vendu 
	    JPanel panel2 = new JPanel();
	    FlowLayout layout2 = new FlowLayout(FlowLayout.LEFT);
	    monPoisson = new JLabel ("Mettre en vente :",JLabel.RIGHT);
	    
	    poisson = new JComboBox();
	    poisson.addItem("saumon");
	    poisson.addItem("truite");
	    poisson.addItem("thon");
	    poisson.addItem("requin");
	    poisson.addItem("sole");
	    poisson.addItemListener(this);
	    
	    panel2.add(monPoisson);
	    panel2.add(poisson);
	    panel2.setLayout(layout2);
	    panel.add(panel2);
	    this.add(panel);
	    
	    // partie inférieure de l'interface
	    JPanel panel3 = new JPanel();
	    FlowLayout layout3 = new FlowLayout(FlowLayout.CENTER);
	    ok = new JButton("Ouvrir une salle de vente");
	    
	    ok.setEnabled(false);
	    ok.addActionListener(this);
	    panel3.add(ok);
	    panel3.setLayout(layout3);
	    panel.add(panel3);
	    this.add(panel);

	    JPanel panel4 = new JPanel();
	    j = new JTextArea(6,25);
	    j.setLineWrap(true);
	    JScrollPane textPane = new JScrollPane(j,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	    panel4.add(textPane);
	    this.add(panel4);
	    
	    this.setLayout(layout);
	    	
	}
 

	/* -------------------- Méthodes qui traite les évènements utilisateurs-------------------*/
	
	/* Méthode qui permet de réagir aux cases à cocher et aux listes d'options */
	public void itemStateChanged(ItemEvent e) {
	    Object type = e.getItem();
	    poissonRecorded  = type.toString();
	}
	
	/* Méthodes qui permettent de réagir aux événements claviers */
	public void keyPressed(KeyEvent e) {
	}
	
	public void keyReleased (KeyEvent e) {
	}
	
	public void keyTyped (KeyEvent e) {
	    if ((prix.getText()== "" )){
		ok.setEnabled(false);
	    }
	    else  {
		ok.setEnabled(true);
	    }
	}
	
	/* Méthode qui permet de réagir aux clics */
	public void actionPerformed(ActionEvent e) {
	    Object source = e.getSource();
	    if (source==ok) {
		initVendeur(nom.getText(),poissonRecorded,prix.getText());
		estInscrit = true;
	    }
	}
    }



    
    /*-------------------------------------------------------------------------------------------------*/
    /*-----------------------------------------  Vendeur  ---------------------------------------------*/
    /*-------------------------------------------------------------------------------------------------*/
    
    /**
     * nom du vendeur
     */
    private String monNom="";
    /**
     * poisson vendu par l'agent Vendeur
     */
    private String monTypeDePoisson="";
    /**
     * lieu de vente de l'agent Vendeur
     */
    private String maPlaceDeVente="salledevente";
    /**
     * groupe de l'agent Vendeur
     */
    private MonGroupFilter groupFilter;
    /**
     * Carte d'accès de l'agent Vendeur
     */
    private String accessCard = "poilauxdents";
    /**
     * adresse de l'agent Matchmaker dont aura besoin l'agent Vendeur pour pouvoir communiquer
     */
    private AgentAddress matchmaker;
    /**
     * prix de base de l'agent Vendeur
     */
    private String monPrix="";
    /**
     * booleen qui teste si un agent Vendeur a rempli tous ses champs (nom, poisson, prix)
     */
    private boolean estInscrit = false;
    JTextArea j;

    VendeurGUI g;


    /**
     * Constructeur qui permet de créer l'interface associée
     * L'utilisateur pourra alors entrer les informations suivantes :
     *     - le nom de l'agent Vendeur
     *     - le type de poisson qu'il vend
     *     - le prix de vente initial
     */
    public Vendeur () {
    }

     public void initGUI() {
       g = new VendeurGUI(this);
       this.setGUIObject(g);
   }
    

    /**
     * Méthode qui permet d'activer l'agent Vendeur
     * pendant cette activation l'agent Vendeur 
     *     - récupère l'adresse de l'agent Matchmaker
     *     - crée un groupe
     */
    public void activate(){

	System.out.println("Activation du vendeur "+monNom);
	do {
	    pause(2000);
	}while(!estInscrit);
	
	// initialiser le filtre	
	groupFilter = new MonGroupFilter(accessCard,"acheteur");
	println(monPrix);
	maPlaceDeVente = "salle de vente " + monTypeDePoisson;
	
	// prendre role member
	requestRole("DESS IHM","market","member",null);
        matchmaker = getAgentWithRole("DESS IHM","market","matchmaker");

	println("Bonjour, je m'appelle "+monNom+" et je suis vendeur de "+ monTypeDePoisson +" au prix de "+monPrix);
	System.out.println("Bonjour,je m'appelle "+monNom+" et je suis vendeur de "+ monTypeDePoisson +" au prix de "+monPrix);


	    
	// creation espace de vente
	createGroup(true,maPlaceDeVente,null,groupFilter);
	
    }
    

    /**
     * Méthode qui gère la vie de l'agent Vendeur
     * Cette méthode gère 
     *     - la demande de référencement auprès du matchmaker
     *     - l'entrée des divers acheteurs
     *     - le déroulement des enchères : les enchères commencent quand 2 agents Acheteurs au moins sont entrés
     */
    
    public void live () {
       
        /* messages reçus */
	ActMessage msg; 
	 /* compteur */
	int cpt = 10;

	boolean isRecorded = false; // on boucle tant que le matchmaker ne nous a pas accepté
	boolean isDead = false; // on agit tant qu on a pas vendu
	
	Vector acheteursPotentiels = new Vector(); // liste qui enregistre les adresses des acheteurs potentiels
	Vector acheteursDeclares = new Vector();  // liste qui enregistre les adresses des acheteurs ayant accepté l'enchère de l'agent Vendeur

	InfoCard infoCard = new InfoCard (this.getAddress(),maPlaceDeVente,monTypeDePoisson,accessCard,monNom);
	
	/* inscription auprès du matchmaker */
	println("Inscription auprès du matchmaker");
	/* on attend l'AR demander referencement */
	while (!isRecorded) {
	    sendMessage(matchmaker,new ActMessage ("demander publier",infoCard));
	    pause(2000);
	    if(!isMessageBoxEmpty()) {	 
		msg = (ActMessage)nextMessage();
		if ( msg.getAction().equals("répondre publier")) {
		    if ((msg.getContent()).equals("oui")) {
			isRecorded = true;
			pause(1000);
		    }
		    else {
			isRecorded = false;
			pause(1000);
		    }
		}
	    }
	    else
		println("Pas de messages reçus: le référencement n'est pas encore effectué ");
	    pause(2000);
	}
	println("Inscription effectuée auprès du matchmaker");

	/* le vendeur attend des acheteurs et procède aux encheres */
	do{
	    pause(7000);
	    println("J'attends des acheteurs potentiels");
	    while (!isMessageBoxEmpty()) {
		msg = (ActMessage)nextMessage();

		/* si demande d'entrée d'un nouvel acheteur */
		if (msg.getAction() == "demander entrer groupe") {
		    AgentAddress temp = (AgentAddress) msg.getObject();
		    if (acheteursPotentiels.size() == 0) {
			acheteursPotentiels.add(temp);
			ActMessage msgAR = new ActMessage("AR demander entrer groupe", temp);
			sendMessage (matchmaker,msgAR);
			groupFilter.allowAgentToTakeRole(temp,"acheteur",accessCard);
			System.out.println("Le vendeur "+monNom+" a autorisé un acheteur à entrer dans mon marché");
			pause(3000);
		    }
		    else {
			if (temp != (AgentAddress)acheteursPotentiels.get(acheteursPotentiels.size()-1)) {
			    acheteursPotentiels.add(temp);
			    ActMessage msgAR = new ActMessage("AR demander entrer groupe", temp);
			    sendMessage (matchmaker,msgAR);
			    groupFilter.allowAgentToTakeRole(temp,"acheteur",accessCard);
			    System.out.println("Le vendeur "+monNom+" a autorisé un acheteur à entrer dans mon marché");
			}			
		    }
		    System.out.println("Le nombre d'acheteurs potentiels est "+ acheteursPotentiels.size());  
		    pause(3000);

		}
	    }
		if ( acheteursPotentiels.size() == 0) {
			cpt= cpt-1;
		}
	    /* 2acheteurs potentiels au moins : les enchères peuvent donc commencer */
	    if ( acheteursPotentiels.size() >= 2) {
		int cmpt =0;
		println (" J'ai au moins 2 acheteurs, je peux donc leur proposer un prix");
		/* si le vendeur a au moins 2 acheteurs,il peut proposer un prix */
		ActMessage msgPrix = new ActMessage("proposer",monPrix);
		for (int i = 0;i<acheteursPotentiels.size();i++) {
		    sendMessage((AgentAddress)acheteursPotentiels.elementAt(i),msgPrix);
		}
		pause(4000);
		
		
		
		/* on récupère les réponses éventuelles */
		while (!isMessageBoxEmpty()) {
		    msg = (ActMessage)nextMessage();
		    if (msg.getAction() == "accepter proposition") {
			acheteursDeclares.add(msg.getSender());
			cmpt ++;
			System.out.println("ok pour prix");
		    }
		    else if (msg.getAction() == "refuser proposition") {
			cmpt ++;
		    }
		    pause(1000);
		}
		System.out.println("il y a "+acheteursDeclares.size() +" acheteurs déclarés");
		
		// on attend que tous les acheteurs aient repondu
		if (cmpt == acheteursPotentiels.size()) {
		    
		    /* on regarde le nombre d'acheteurs déclarés */
		    /* 1. cas où aucun acheteur n'est intéressé */
		    if ( acheteursDeclares.size() == 0) {
			// le vendeur doit baisser les prix
			println("aucune proposition, bouh!!!!!!!!!!");
			int tmp2 = Integer.parseInt(monPrix) - 10;
			monPrix = Integer.toString(tmp2);
			acheteursDeclares.removeAllElements();
			println("C'est les soldes! "+ monPrix);
		    }
		    
		    /* 2. cas où 2 acheteurs au moins sont intéressés */
		    if ( acheteursDeclares.size() >= 2) {
			// le vendeur augmente les prix
			int tmp = Integer.parseInt(monPrix) + 10;
			monPrix = Integer.toString(tmp);
			acheteursDeclares.removeAllElements();
			System.out.println("Les prix montent!"+monPrix);
			
		    }
		    
		    /* 3. cas où un seul acheteur est interéssé */
		    if ( acheteursDeclares.size() == 1) {
			// le poisson est attribué à l'acheteur intéressé
			AgentAddress adresseGagnant = (AgentAddress)acheteursDeclares.firstElement();
			sendMessage(adresseGagnant, new ActMessage("informer gagnant",null));
			println("adjugé vendu");
			System.out.println("adjugé vendu pour "+monPrix);
			
			// le vendeur doit aussi informer les perdants
			for (int j = 0; j < acheteursPotentiels.size(); j++){
			    if ((AgentAddress)acheteursPotentiels.get(j) != adresseGagnant) {
				AgentAddress adressePerdant = (AgentAddress)acheteursPotentiels.get(j);
				sendMessage(adressePerdant, new ActMessage("informer fin",adresseGagnant));
			    }
			}
			
			/* maintenant le vendeur peut quitter la salle */
			isDead = true;
		    }
		}
	    }
	}while((!isDead)&&(cpt>0));
    }
    

    /**
     * Méthode qui gère la fin de vie de l'agent Vendeur
     * L'agent Vendeur se suicidera quand il aura vendu son poisson, donc quand l'enchère sera finie
     */
    public void end(){
	ActMessage msgFin = new ActMessage("informer suicide",null);
	sendMessage(matchmaker,msgFin);
	println("Le vendeur "+monNom+"s'en va!");
	System.out.println("Le vendeur "+monNom+"s'en va!");
	pause(2000);
    }


    /*-------------------------------------Méthodes utiles-----------------------------------------*/
    /**
     * Méthode qui initialise les caractéristiques de l'agent Vendeur à savoir :
     *      - son nom
     *      - le type de poisson qu'il vend
     *      - le prix de vente initial
     * @param nom le nom du vendeur
     * @param poisson le type de poisson vendu par l'agent Vendeur
     * @param prix le prix de vente initial du poisson
     *
     */
    public void initVendeur(String nom, String poisson, String prix) {
	this.monNom = nom;
	this.monTypeDePoisson = poisson;
	this.monPrix = prix;

    
    }

    public void println(String s) {
	j.append(s +"\n");
    }

    /*---------------------------------------fin de la classe Vendeur--------------------------------*/
}


 

	    
	
	
	


		
			


		
			
