package fr.univ.lyon1.server;

import fr.univ.lyon1.common.Message;
import fr.univ.lyon1.common.User;
import fr.univ.lyon1.server.models.UserModel;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class ConnectedClient implements Runnable {
    private static int idCounter = 0;
    private final int id = idCounter++;
    private final Server server;
    private final Socket socket;
    private final ObjectOutputStream out;
    private ObjectInputStream in;
    private User user;

    ConnectedClient(Server server, Socket socket) throws IOException {
        this.server = server;
        this.socket = socket;
        this.out = new ObjectOutputStream(socket.getOutputStream());

        System.out.println("New user try to auth");
        while (!this.auth());
    }

    private boolean auth() throws IOException {
        if (in == null)
            in = new ObjectInputStream(socket.getInputStream());

        String username = in.readUTF();
        System.out.println("username: "+username);
        String password = in.readUTF();
        System.out.println("Pass: "+password);

        if (username.isEmpty() || password.isEmpty()) {
            out.writeUTF("err: Login required");
            out.flush();
            return false;
        }

        UserModel user = UserModel.get(username);

        if (user == null)
            out.writeUTF("err: Username not found !");
        else if (!user.checkPassword(password))
            out.writeUTF("err: Password invalid !");
        else {
            out.writeUTF("logged");
            out.flush();
            this.user = user;
            return  true;
        }
        out.flush();

        return false;
    }

    public Message sendMessage(Message message) throws IOException {
        out.writeObject(message);
        out.flush();
        return message;
    }

    public void run() {
        try {
            while (true) {
                Message msg = (Message) in.readObject();

                if (msg == null)
                    break;

                msg.setSender(this.user);
                server.broadcastMessage(msg, id);
            }
        } catch (IOException | ClassNotFoundException e) {
            if (!(e instanceof EOFException)) {
                System.err.println("Client connection error");
                e.printStackTrace();
            }
        } finally {
            server.disconnectedClient(this);
        }
    }

    public void closeClient() throws IOException {
        if (in != null)
            in.close();
        out.close();
        socket.close();
    }

    public int getId() {
        return id;
    }
}