package eu.hgross.blaubot.core;
import java.util.List;
import eu.hgross.blaubot.core.acceptor.ConnectionMetaDataDTO;
import eu.hgross.blaubot.core.acceptor.IBlaubotIncomingConnectionListener;
import eu.hgross.blaubot.core.acceptor.IBlaubotListeningStateListener;
import eu.hgross.blaubot.core.acceptor.discovery.IBlaubotBeacon;
import eu.hgross.blaubot.core.acceptor.discovery.IBlaubotBeaconStore;
import eu.hgross.blaubot.core.acceptor.discovery.IBlaubotDiscoveryEventListener;
import eu.hgross.blaubot.core.statemachine.events.AbstractBlaubotDeviceDiscoveryEvent;
import eu.hgross.blaubot.core.statemachine.events.DiscoveredKingEvent;
import eu.hgross.blaubot.core.statemachine.states.IBlaubotState;
import eu.hgross.blaubot.admin.ACKPronouncePrinceAdminMessage;
import eu.hgross.blaubot.admin.AbstractAdminMessage;
import eu.hgross.blaubot.admin.BowDownToNewKingAdminMessage;
import eu.hgross.blaubot.admin.DiscoveredDeviceAdminMessage;
import eu.hgross.blaubot.admin.PrinceFoundAKingAdminMessage;
import eu.hgross.blaubot.admin.PronouncePrinceAdminMessage;
import eu.hgross.blaubot.messaging.IBlaubotAdminMessageListener;
import eu.hgross.blaubot.util.Log;
/**
* A beacon implementation that is added to every blaubot instance.
* It does not discover anything but hears for admin messages to emulate discovery events.
* That is if a prince found a king and sends the PrinceFoundAKing Admin message.
*/
public class AdminMessageBeacon implements IBlaubotBeacon, IBlaubotAdminMessageListener {
private static final String LOG_TAG = "AdminMessageBeacon";
private IBlaubotDiscoveryEventListener discoveryEventListener;
private IBlaubotBeaconStore beaconStore;
private IBlaubotListeningStateListener listeningStateListener;
private volatile boolean started;
private Blaubot blaubot;
@Override
public void onAdminMessage(AbstractAdminMessage adminMessage) {
if(adminMessage instanceof PrinceFoundAKingAdminMessage) {
final PrinceFoundAKingAdminMessage princeFoundAKingAdminMessage = (PrinceFoundAKingAdminMessage) adminMessage;
IBlaubotDevice discoveredKingDevice = new BlaubotDevice(princeFoundAKingAdminMessage.getKingsUniqueDeviceId());
final List<ConnectionMetaDataDTO> connectionMetaDataList = princeFoundAKingAdminMessage.getConnectionMetaDataList();
final DiscoveredKingEvent event = new DiscoveredKingEvent(discoveredKingDevice, connectionMetaDataList);
if (Log.logDebugMessages()) {
Log.d(LOG_TAG, "Propagating DiscoveredKing event ");
}
// trigger listener
if (discoveryEventListener != null ) {
discoveryEventListener.onDeviceDiscoveryEvent(event);
}
} else if(adminMessage instanceof BowDownToNewKingAdminMessage) {
final BowDownToNewKingAdminMessage bowDownToNewKingAdminMessage = (BowDownToNewKingAdminMessage) adminMessage;
final List<ConnectionMetaDataDTO> newKingsConnectionMetaDataList = bowDownToNewKingAdminMessage.getNewKingsConnectionMetaDataList();
final String kingsUniqueDeviceId = bowDownToNewKingAdminMessage.getNewKingsUniqueDeviceId();
beaconStore.putConnectionMetaData(kingsUniqueDeviceId, newKingsConnectionMetaDataList);
} else if(adminMessage instanceof PronouncePrinceAdminMessage) {
final PronouncePrinceAdminMessage pronouncePrinceAdminMessage = (PronouncePrinceAdminMessage) adminMessage;
final String uniqueDeviceId = pronouncePrinceAdminMessage.getUniqueDeviceId();
final List<ConnectionMetaDataDTO> connectionDataList = pronouncePrinceAdminMessage.getConnectionDataList();
if(uniqueDeviceId != null && connectionDataList != null) {
// possible if king never got a beacon message from the prince before
beaconStore.putConnectionMetaData(uniqueDeviceId, connectionDataList);
}
} else if(adminMessage instanceof ACKPronouncePrinceAdminMessage) {
final ACKPronouncePrinceAdminMessage ackAdminMessage = (ACKPronouncePrinceAdminMessage) adminMessage;
final String uniqueDeviceId = ackAdminMessage.getUniqueDeviceId();
final List<ConnectionMetaDataDTO> connectionDataList = ackAdminMessage.getConnectionDataList();
if(uniqueDeviceId == null && connectionDataList == null) {
// should never happen
throw new RuntimeException("Got incomplete data in prince ack: " + adminMessage);
}
beaconStore.putConnectionMetaData(uniqueDeviceId, connectionDataList);
} else if(adminMessage instanceof DiscoveredDeviceAdminMessage) {
final DiscoveredDeviceAdminMessage discoveredDeviceAdminMessage = (DiscoveredDeviceAdminMessage) adminMessage;
final AbstractBlaubotDeviceDiscoveryEvent discoveryEvent = discoveredDeviceAdminMessage.createDiscoveryEvent();
// trigger listener
if (discoveryEventListener != null ) {
discoveryEventListener.onDeviceDiscoveryEvent(discoveryEvent);
}
}
}
@Override
public void setBlaubot(Blaubot blaubot) {
this.blaubot = blaubot;
}
@Override
public void setBeaconStore(IBlaubotBeaconStore beaconStore) {
this.beaconStore = beaconStore;
}
@Override
public void setDiscoveryEventListener(IBlaubotDiscoveryEventListener discoveryEventListener) {
this.discoveryEventListener = discoveryEventListener;
}
@Override
public void onConnectionStateMachineStateChanged(IBlaubotState state) {
// ignore
}
@Override
public void setDiscoveryActivated(boolean active) {
// ignore, we don't discover
}
@Override
public IBlaubotAdapter getAdapter() {
return null; // ignore, no problem
}
@Override
public void startListening() {
// call listener
started = true;
if (listeningStateListener != null) {
listeningStateListener.onListeningStarted(this);
}
}
@Override
public void stopListening() {
// call listener
started = false;
if (listeningStateListener != null) {
listeningStateListener.onListeningStopped(this);
}
}
@Override
public boolean isStarted() {
return started;
}
@Override
public void setListeningStateListener(IBlaubotListeningStateListener stateListener) {
this.listeningStateListener = stateListener;
}
@Override
public void setAcceptorListener(IBlaubotIncomingConnectionListener acceptorListener) {
// ignore
}
@Override
public ConnectionMetaDataDTO getConnectionMetaData() {
// ignore
return null;
}
}