// Seller.Java
package ld5_2;
import java.time.Year;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import jade.content.ContentElement;
import jade.content.ContentManager;
import jade.content.lang.Codec;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.TickerBehaviour;
import ld5_2.ontology.BuyCar;
import ld5_2.ontology.BuyCarMsg;
import ld5_2.ontology.BuyCarResponse;
import ld5_2.ontology.BuyCarResponseMsg;
import ld5_2.ontology.CarData;
import ld5_2.ontology.CarList;
import ld5_2.ontology.CarListMsg;
import ld5_2.ontology.CarMaker;
import ld5_2.ontology.CarModel;
import ld5_2.ontology.CarOntology;
import ld5_2.ontology.CarSearch;
import ld5_2.ontology.CarSearchMsg;
import ld5_2.ontology.Zmogus;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;


public class Seller extends Agent {
    Zmogus owner;
    CarMaker make;
    CarModel model;
    CarData car;
    LinkedList<CarData> carlist = new LinkedList<CarData>();
    private final Set<Integer> soldVINs = new HashSet<>();
    int idCounter = 0;

    private void print(String data, String elgesenosId) {
        if (elgesenosId != null) {
            System.out.println("A[" + getLocalName() + " | " + elgesenosId + "] " + data);
        } else {
            System.out.println("A[" + getLocalName() + "] " + data);
        }
    }

    private CarData createCar(String country, String makeName, String modelName, String modif, String color, String engine, int year, int price) {
        idCounter++;
 
        CarMaker make = new CarMaker();
        make.setGID(idCounter * 1000 + 1);
        make.setCountry(country);
        make.setMakeName(makeName);
 
        CarModel model = new CarModel();
        model.setMID(idCounter * 1000 + 11);
        model.setMaker(make);
        model.setModelName(modelName);
        model.setModification(modif);
 
        CarData car = new CarData();
        car.setVIN(idCounter * 1000 + 111);
        car.setModel(model);
        car.setColor(color);
        car.setEngine(engine);
        car.setOwner(owner);
        car.setYearBuilt(year);
        car.setCarPrice(price);
 
        return car;
    }

    private void printCarList() {
        for (CarData cd : carlist) {
            boolean sold = soldVINs.contains(cd.getVIN());
            System.out.printf("  VIN=%-6d  %-7s  %-10s  %-8s  %-6s  %-6s  %d  %d€  %s%n",
                cd.getVIN(),
                cd.getModel().getMaker().getMakeName(),
                cd.getModel().getModelName(),
                cd.getModel().getModification(),
                cd.getColor(),
                cd.getEngine(),
                cd.getYearBuilt(),
                cd.getCarPrice(),
                sold ? "[SOLD]" : "");
        }
    }

    private class WaitForMessagesCarSearch extends CyclicBehaviour 
    {
        @Override
        public void action() 
        {               
            Ontology onto = CarOntology.getInstance();
            Codec codec = new SLCodec();
            ContentManager cm = getContentManager();
            cm.registerLanguage(codec);
            cm.registerOntology(onto);
            
            MessageTemplate mt = MessageTemplate.MatchConversationId("car-search");
            ACLMessage msg = myAgent.receive(mt);
                        
            if (msg != null) 
                 {                
                try
                {                    
                    String pran = msg.getContent();
                    print("Message received: "+pran, "WaitForMessagesCarSearch");
                    
                    ContentElement c = cm.extractContent(msg);
                    
                    if (c instanceof CarSearchMsg)
                    {
                        CarSearchMsg p = (CarSearchMsg) c;                        
                        
                        CarSearch cs = p.getCarSearchLine();
                        CarList found = new CarList();
                        for (CarData cd : carlist) {
                            if (soldVINs.contains(cd.getVIN())) continue;

                            boolean priceOk = cd.getCarPrice() >= cs.getPriceFrom() && cd.getCarPrice() <= cs.getPriceTo();
                            boolean yearOk = cd.getYearBuilt() >= cs.getYearFrom() && cd.getYearBuilt() <= cs.getYearTo();
                            boolean countryOk = cs.getCountry() == null || cs.getCountry().isBlank() || cs.getCountry().equalsIgnoreCase( cd.getModel().getMaker().getCountry());

                            if (priceOk && yearOk && countryOk) {
                                found.addList(cd);
                            }
                        }

                        // Surenkame atsakymą
                        CarListMsg o = new CarListMsg();
                        o.setCarListLine(found);
                
                        ACLMessage omsg = new ACLMessage(ACLMessage.INFORM);
                        omsg.setLanguage(codec.getName()); 
                        omsg.setOntology(onto.getName());
                        omsg.setConversationId(msg.getConversationId());
                        omsg.setInReplyTo(msg.getReplyWith());
                        omsg.clearAllReceiver();     
                        omsg.addReceiver(msg.getSender());
                        omsg.setConversationId("car-list");
                
                        cm.fillContent(omsg, o);                        
                        send(omsg);  
                    }                
                    else
                    {
                        print("received unknown message: " + pran, "WaitForMessagesCarSearch");
                    }
                } 
                catch (Exception ex)
                {
                    print("Ontology parsing error: "+ ex.getMessage(), "WaitForMessagesCarSearch");
                }
            }
            else block();
        }
    }

    private class WaitForMessagesCarBuyMsg extends CyclicBehaviour 
    {
        @Override
        public void action() 
        {               
            Ontology onto = CarOntology.getInstance();
            Codec codec = new SLCodec();
            ContentManager cm = getContentManager();
            cm.registerLanguage(codec);
            cm.registerOntology(onto);
            
            MessageTemplate mt = MessageTemplate.MatchConversationId("car-buy");
            ACLMessage msg = myAgent.receive(mt);
                        
            if (msg != null) 
            {                
                try
                {                    
                    String pran = msg.getContent();
                    print("Message received: "+pran, "WaitForMessagesCarBuyMsg");
                    
                    ContentElement c = cm.extractContent(msg);
                    
                    if (c instanceof BuyCarMsg)
                    {
                        BuyCarMsg p = (BuyCarMsg) c;
                        
                        BuyCar l = p.getBuyCarLine();
                        int vin = l.getVIN();
                        // print("Comfirmation to buy the car: \""+l.getVIN(), "WaitForMessagesCarBuyMsg");

                                                CarData found = null;
                        for (CarData cd : carlist) {
                            if (cd.getVIN() == vin) { found = cd; break; }
                        }

                        BuyCarResponse r = new BuyCarResponse();
                        r.setVIN(vin);

                        if (found == null) {
                            r.setIsApproved(false);
                            r.setReason("car VIN=" + vin + " cant find.");
                            print("cant find", "WaitForBuyCar");
                        } else if (soldVINs.contains(vin)) {
                            r.setIsApproved(false);
                            r.setReason("car VIN=" + vin + " already sold.");
                            print("already sold", "WaitForBuyCar");
                        } else {
                            soldVINs.add(vin);              // pažymime kaip parduotą
                            r.setIsApproved(true);
                            r.setPrice(found.getCarPrice());
                            r.setReason("");
                            print("sold VIN=" + vin + " cost=" + found.getCarPrice(), "WaitForBuyCar");
                        }

                        BuyCarResponseMsg o = new BuyCarResponseMsg();
                        o.setBuyCarResLine(r);
                
                        ACLMessage omsg = new ACLMessage(ACLMessage.INFORM);
                        omsg.setLanguage(codec.getName()); 
                        omsg.setOntology(onto.getName());
                        omsg.setConversationId(msg.getConversationId());
                        omsg.setInReplyTo(msg.getReplyWith());
                        omsg.clearAllReceiver();     
                        omsg.addReceiver(msg.getSender());
                        omsg.setConversationId("car-buy-res");
                
                        cm.fillContent(omsg, o);                        
                        send(omsg);  
                    }    
                    else
                    {
                        print("received unknown message: " + pran, "WaitForMessagesCarSearch");
                    }
                } 
                catch (Exception ex)
                {
                    print("Ontology parsing error: "+ ex.getMessage(), "WaitForMessagesCarSearch");
                }
            }
            else block();
        }
    }

    @Override 
    public void setup() {
        owner = new Zmogus();
        owner.setID("z1");
        owner.setAddress("vilnius2");
        owner.setLastName("Petrauskas");
        owner.setName("Jonas");

        carlist.add(createCar("Japan", "Honda", "Celica", "mk2", "Red", "V6", 2001, 20000));
        carlist.add(createCar("Japan", "Honda", "Supra", "mk4", "Yellow", "V6", 2003, 40000));
        carlist.add(createCar("Japan", "Nissan", "GTR", "R34", "Black", "V6", 2000, 50000));
        carlist.add(createCar("Sweden", "Volvo", "V70", "p2", "Blue", "I5", 2005, 10000));

        addBehaviour(new WaitForMessagesCarSearch());
        addBehaviour(new WaitForMessagesCarBuyMsg());
    }


    @Override  
    public void takeDown() 
    {     
    } 
}