package com.zepchat.core;

import com.zepchat.core.data.ChatSession;
import com.zepchat.core.data.Message;
import com.zepchat.core.data.User;
import com.zepchat.core.transport.ZEPDiscoveryTransport;
import com.zepchat.core.transport.ZEPMessagingTransport;
import com.zepchat.core.transport.ZEPDiscoveryTransport.UserStatusListener;
import com.zepchat.core.transport.ZEPMessagingTransport.MessageListener;
import com.zepchat.core.transport.discovery.SSDPDiscoveryTransport;
import com.zepchat.core.transport.messaging.HttpMessagingTransport;
import com.zepchat.core.util.JavaLogger2LogCat;
import zutil.log.LogUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;

/**
 * Created by Ziver on 2014-11-06.
 */
public class ZEPCore implements MessageListener, UserStatusListener {
    public static final int POLL_TIME = 5000;

    private ZEPDiscoveryTransport.UserStatusListener userListener;
    private MessageListener msgListener;
    private User msgListener4User;

    private ZEPDiscoveryTransport discoveryTransport;
    private ZEPMessagingTransport msgTransport;
    private List<User> activeUsers;

    private User localUser;
    private HashMap<User,ChatSession> sessions;


    public ZEPCore(User localUser) throws IOException{
        LogUtil.addGlobalHandler(new JavaLogger2LogCat());
        LogUtil.setGlobalLevel(Level.FINEST);

        this.sessions = new HashMap<User,ChatSession>();
        this.localUser = localUser;

        activeUsers = new ArrayList<User>();
        discoveryTransport = new SSDPDiscoveryTransport(this, localUser);
        discoveryTransport.setUserStatusListener(this);
        discoveryTransport.start();
        msgTransport = new HttpMessagingTransport(this, localUser);
        msgTransport.setMessageListener(this);

        new Thread(new Runnable() {
            @Override
            public void run(){
                while(true){
                    try {Thread.sleep(POLL_TIME);} catch (InterruptedException e) {  }
                    scan();
                }
            }
        }).start();
    }

    public void scan() {
        discoveryTransport.scan();
    }


    public void close(){
        discoveryTransport.close();
        msgTransport.close();
    }

    public void setUserStatusListener(UserStatusListener userListener){
        this.userListener = userListener;
    }

    public void setMessageListener(MessageListener msgListener) {
        this.msgListener4User = null;
        this.msgListener = msgListener;
    }
    public void setMessageListener(User user, MessageListener msgListener){
        this.msgListener4User = user;
        this.msgListener = msgListener;
    }

    @Override
    public void newMessage(Message message) {
        if(!sessions.containsKey(message.getUser()))
            sessions.put(message.getUser(), new ChatSession());
        sessions.get(message.getUser()).add(message);
        if(msgListener != null && (msgListener4User == null || msgListener4User.equals(message.getUser())))
            msgListener.newMessage(message);
    }

    public void sendMessage(User toUser, Message msg) {
        msgTransport.sendMessage(toUser, msg.getMessage());
        sessions.get(toUser).add(msg);
        if(msgListener != null)
            msgListener.newMessage(msg);
    }

    @Override
    public void addRemoteUser(User user) {
        if(user.getPublicKey() == null)
            return;
        if(getRemoteUser(user.getPublicKey()) == null){
            activeUsers.add(user);
            if(userListener != null)
                userListener.addRemoteUser(user);
        }
        getRemoteUser(user.getPublicKey()).setLastSeen(System.currentTimeMillis());
    }
    public void removeRemoteUser(User user) {
        if(user.getPublicKey() == null)
            return;
        if(getRemoteUser(user.getPublicKey()) != null){
            activeUsers.remove(user);
            if(userListener != null)
                userListener.removeRemoteUser(user);
        }
    }


    public User getLocalUser() {
        return localUser;
    }

    public User getRemoteUser(String publicKey){
        if(publicKey != null) {
            for (User user : activeUsers) {
                if (publicKey.equals(user.getPublicKey()))
                    return user;
            }
        }
        return null;
    }



    public ChatSession getSession(User remoteUser) {
        if (!sessions.containsKey(remoteUser))
            sessions.put(remoteUser, new ChatSession());
        return sessions.get(remoteUser);
    }

    public List getRemoteUserList() {
        return activeUsers;
    }
}
