package hsr.dsa.network;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import hsr.dsa.network.data.ChatMessage;
import hsr.dsa.network.data.DHTGroup;
import hsr.dsa.network.data.FriendRequest;
import hsr.dsa.network.data.GroupInvite;
import net.tomp2p.peers.Number160;

public class NetworkListener implements Runnable {
	private static final Logger log = LoggerFactory.getLogger(NetworkListener.class);
	private final DataClient client;
	private final NetworkEventHandler eventHandler;

	public NetworkListener(DataClient client, NetworkEventHandler eventHandler) {
		super();
		this.client = client;
		this.eventHandler = eventHandler;
	}

	@Override
	public void run() {
		try {
			this.setActive();
			this.updateFriendList();
			this.handleFriendRequest();
			this.handleGroupInvite();
			this.handleDirectMessage();
			this.handleGroupMessage();
		} catch (IOException e) {
			log.error("error checking for messages", e);
		} catch (ClassNotFoundException e) {
			log.error("error checking for messages", e);
			throw new RuntimeException(e);
		}
	}

	private void setActive() throws ClassNotFoundException, IOException {
		this.client.getProfile(this.eventHandler.getListenAddress(), (profile) -> {
			try {
				if(profile != null) {
					profile.updateLastActivity();
					this.client.put(this.eventHandler.getListenAddress(), profile, (success) -> {});
				}
			} catch (IOException e) {
				log.error("error updateing profile", e);
			}
		});
	}

	private void updateFriendList() {
		for (AcitveProfile friend : this.eventHandler.getFriendList()) {
			try {
				this.client.getProfile(friend.getId(), (profile) -> {
					if(profile != null) {
						friend.setLastActivity(profile.getLastActivity());
					}
				});
			} catch (ClassNotFoundException | IOException e) {
				log.error("error updateing friend profile: " + friend.getId(), e);
			}
		}
	}

	private void handleFriendRequest() throws ClassNotFoundException, IOException {
		this.client.getAll(this.eventHandler.getListenAddress(), FriendRequest.class, true, (friendRequests) -> {
			for (FriendRequest friendRequest : friendRequests) {
				this.eventHandler.onFriendRequest(friendRequest);
			}
		});
	}

	private void handleGroupInvite() throws ClassNotFoundException, IOException {
		this.client.getAll(this.eventHandler.getListenAddress(), GroupInvite.class, true, (groupInvites) -> {
			for (GroupInvite groupInvite : groupInvites) {
				this.eventHandler.onGroupInvite(groupInvite);
			}
		});
	}

	private void handleDirectMessage() throws ClassNotFoundException, IOException { // TODO decryption
		this.client.getAll(this.eventHandler.getListenAddress(), ChatMessage.class, true, (messages) -> {
			for (ChatMessage message : messages) {
				this.eventHandler.onDirectMessage(message);
			}
		});
	}

	private void handleGroupMessage() throws ClassNotFoundException, IOException {
		for (DHTGroup group : eventHandler.getRegisteredGroups()) {
			this.client.getAll(Number160.createHash(group.getId()), ChatMessage.class, (messages) -> {
				for (ChatMessage message : messages) {
					this.eventHandler.onGroupMessage(message, group);
				}
			});
		}
	}
}
