package electrosphere.net.client;

import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.raw.NetworkParser;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.net.SocketException;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.crypto.stream.CryptoInputStream;
import org.apache.commons.crypto.stream.CryptoOutputStream;

/**
 *
 * @author amaterasu
 */
public class ClientNetworking implements Runnable{
    
    
    Socket socket;
//    CryptoInputStream inputStream;
//    CryptoOutputStream outputStream;
    InputStream inputStream;
    OutputStream outputStream;
    boolean initialized;
    NetworkParser parser;
    
    ClientProtocol clientProtocol = new ClientProtocol();
    
    public ClientNetworking(String address, int port){
        try {
            this.socket = new Socket(address,port);
        } catch (IOException ex) {
            System.err.println("Failed to connect!");
            ex.printStackTrace();
            System.exit(1);
        }
    }
    
    
    
    @Override
    public void run(){
        initialized = false;
            //        final SecretKeySpec key = new SecretKeySpec(("1234567890123456").getBytes(),"AES");
//        final Properties properties = new Properties();
//        final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(4096, BigInteger.probablePrime(4000, new Random()));
//        try {
//            inputStream = new CryptoInputStream("AES/ECB/PKCS5Padding",properties,socket.getInputStream(),key,spec);
//        } catch (IOException ex) {
//            ex.printStackTrace();
//            System.exit(1);
//        }
//        try {
//            outputStream = new CryptoOutputStream("AES/ECB/PKCS5Padding",properties,socket.getOutputStream(),key,spec);
//        } catch (IOException ex) {
//            ex.printStackTrace();
//            System.exit(1);
//        }
        try {
            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();
            parser = new NetworkParser(inputStream,outputStream);
        } catch (IOException ex) {
            Logger.getLogger(ClientNetworking.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        initialized = true;
        while(Main.isRunning()){
            //attempt poll incoming messages
            parser.readMessagesIn();
            //outgoing messages
            parser.pushMessagesOut();
        }
    }
    
    
    public void parseMessages(){
        if(initialized){
            while(parser.hasIncomingMessaage()){
                NetworkMessage message = parser.popIncomingMessage();
                LoggerInterface.loggerNetworking.DEBUG("New message " + message.getType());
                //do something
                clientProtocol.handleMessage(message);
            }
        }
    }
    
    
    public void queueOutgoingMessage(NetworkMessage message){
        parser.addOutgoingMessage(message);
    }
    
    public ClientProtocol getClientProtocol(){
        return clientProtocol;
    }
    
}
