package agent;

import features.LocationService;
import features.Log;
import gui.OrderListActivity;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.UnreadableException;
import jade.util.leap.Set;
import jade.util.leap.SortedSetImpl;

import java.io.IOException;

import structures.ExpertData;
import agent.behaviours.ReceiveMessagesBehaviour;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.widget.Toast;

import communication.ExpertMessage;
import communication.Message;
import communication.MessageType;

/**
 * Agent dla wersji Android
 * 
 * @author Mateusz Kaflowski
 * 
 */
public class ExpertAgent extends Agent {
	private static final long serialVersionUID = 9874421614291L;


	/** Context */
	private Context context;
	/** Aktywność chatu */
	OrderListActivity activity;

	private ExpertData expert;

	private ReceiveMessagesBehaviour receiveBehaviour;

	/**
	 * Inicjalizacja agenta
	 */
	protected void setup() {

		Object[] args = getArguments();
		if (args != null && args.length > 0) {
			if (args[0] instanceof Context) {
				context = (Context) args[0];
			}
		}

		AgentManager.setAgent(this);
		
		SharedPreferences settings = context.getSharedPreferences(
				"jadeChatPrefsFile", 0);
		String category = settings.getString("category", "");
		this.setExpert(new ExpertData(this.getAID()
				.getLocalName(), category, this.getAID()));

		// serwis z lokalizacją
		context.startService(new Intent(context, LocationService.class));

		Intent broadcast = new Intent();
		broadcast.setAction("jade.demo.chat.SHOW_CHAT");
		context.sendBroadcast(broadcast);

		// odbieranie wiadomości:
		receiveBehaviour = new ReceiveMessagesBehaviour(activity);
		addBehaviour(receiveBehaviour);

	}

	@Override
	protected void takeDown() {
		context.stopService(new Intent(context, LocationService.class));

		sendDeregistrationMessage();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		AgentManager.agent = null;
		if (activity != null)
			activity.finish();
		super.takeDown();
	}

	/**
	 * Wpisanie się do czatu.
	 */
	public void sendRegistrationMessage() {
		Log.logp(this, "1registration message sent");
		addBehaviour(new OneShotBehaviour(this) {

			@Override
			public void action() {
				ExpertMessage expertMessage = new ExpertMessage(
						myAgent.getAID(), expert);
				expertMessage.setAid(myAgent.getAID());
				expertMessage.setType(MessageType.REGISTRATION);

				// wyszukanie managera:
				DFAgentDescription dfd = new DFAgentDescription();
				ServiceDescription sd = new ServiceDescription();
				sd.setType("Manager");

				dfd.addServices(sd);

				try {
					DFAgentDescription results[] = DFService.search(myAgent,
							dfd);

					ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
					if (results.length != 0) {
						Log.logp(myAgent, Integer.toString(results.length));
						msg.addReceiver(results[0].getName());
						msg.setContentObject(expertMessage);
						send(msg);
						Log.logp(myAgent, "registration message sent");
					} else {
						Log.logp(myAgent, "there is no chat manager");
						myAgent.doDelete();
						return;
					}

				} catch (FIPAException e) {
					Log.logp(myAgent, "FIPAException - due to searching");
					return;
				} catch (IOException e) {
					Log.logp(myAgent, "adding content object error");
					return;
				}

			}
		});
	}

	/**
	 * Wypisanie się z czatu.
	 */
	public void sendDeregistrationMessage() {

		// ustawienie nadawcy:
		ExpertMessage message = new ExpertMessage(this.getAID(), expert);
		message.setAid(this.getAID());
		message.setType(MessageType.DEREGISTRATION);

		DFAgentDescription dfd = new DFAgentDescription();
		ServiceDescription sd = new ServiceDescription();
		sd.setType("Manager");

		dfd.addServices(sd);

		try {
			DFAgentDescription results[] = DFService.search(this, dfd);

			ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
			if (results.length != 0) {
				msg.addReceiver(results[0].getName());
				msg.setContentObject(message);
				send(msg);
			} else {
				Log.logp(this, "there is no chat manager");
				return;
			}

		} catch (FIPAException e) {
			Log.logp(this, "FIPAException - due to searching");
			return;
		} catch (IOException e) {
			Log.logp(this, "sending serialized data message");
			return;
		}

		Log.logp(this, "deregistration message sent");

	}

	/**
	 * Wysłanie wiadomości
	 * 
	 * @param message
	 *            wiadomośc
	 */
	public void sendMessage(final Message message) {
		addBehaviour(new OneShotBehaviour(this) {

			@Override
			public void action() {
				// ustawienie nadawcy:
				message.setAid(myAgent.getAID());

				DFAgentDescription dfd = new DFAgentDescription();
				ServiceDescription sd = new ServiceDescription();
				sd.setType("Manager");

				dfd.addServices(sd);

				try {
					DFAgentDescription results[] = DFService.search(myAgent,
							dfd);

					ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
					if (results.length != 0) {
						msg.addReceiver(results[0].getName());
						msg.setContentObject(message);
						send(msg);
					} else {
						Log.logp(myAgent, "there is no chat manager");
						return;
					}

				} catch (FIPAException e) {
					Log.logp(myAgent, "FIPAException - due to searching");
					return;
				} catch (IOException e) {
					Log.logp(myAgent, "sending serialized data message");
					return;
				}

				Log.logp(myAgent, "message sent");

			}
		});
	}

	/**
	 * 
	 * @param activity
	 *            aktywność chatu
	 */
	public void setActivity(OrderListActivity activity) {
		this.activity = activity;
		receiveBehaviour.setActivity(activity);
	}

	public void setExpert(ExpertData expert) {
		this.expert = expert;
	}

	public ExpertData getExpertData() {
		return expert;
	}

}
