import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

public class Servers {
    static List<ConnectionToClient> clients = new ArrayList<>(); //모든 클라이언트
    static List<ConnectionToClient> Waiting_room = new ArrayList<>(); //대기방을 보는 곳
    static  HashMap<String,List<ConnectionToClient>> room = new HashMap<String, List<ConnectionToClient>>(); //클라이언트 들을 담는 해쉬맵 (방)
    static List<ConnectionToClient> room_out = new ArrayList<>();


    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(8888);
            Socket socket = null;
            while ((socket = server.accept()) != null) {
                new ServerThread(socket).start();
            }
            server.close();
        } catch (Exception e) {
        }
    }

    static class ServerThread extends Thread {
        Socket socket;
        ConnectionToClient conToClient;

        ServerThread(Socket socket) throws IOException {
            this.socket = socket;
            this.conToClient = new ConnectionToClient(socket);


        }
        public void run() {
            try {
                String input = "";


                while( (input = conToClient.read())!=null){
					System.out.println("everything : " + input);
                    String msgs[]=input.split("\\|");
                    String protocol = msgs[0];

                    if(protocol.equals("room")){ //만약 방을 만드는 명령어라면
                        List<ConnectionToClient> clients_for_room  = new ArrayList<>();
                        clients_for_room.add(conToClient);
                        room.put(msgs[1],clients_for_room);
                        System.out.println("make room hash : " + room);
                        clients.add(conToClient);
                        clients_for_room = null;

                    }else if(protocol.equals("join")){ //만약 방을 들어가려는 명령어라면
						List<ConnectionToClient> clients_join_room  = new ArrayList<>();
						clients_join_room =  room.get(msgs[1]); //방의 이름						
                        clients_join_room.add(conToClient);
                        room.put(msgs[1],clients_join_room);
                        System.out.println("join room hash : " + room);
						clients.add(conToClient);
						sendToAll(msgs[2],"join"); //나의 닉네임
                    }
					else if(protocol.equals("chat")){ //만약 채팅을 치려는 명령어라면
                        String key = msgs[1] ;
                        sendToAll(msgs[2],key);
                    } else if (protocol.equals("room_list")){ //방목록을 조회하려는 것이라면
                        System.out.println("room list okay");
                        Set<String> keys = room.keySet();
                     ArrayList<String> list = new ArrayList<String>();

                        for (String key : keys) {

                            Object o = room.get(key);
                            String a = String.valueOf(o);
                            String[] ab = a.split(",");
                            if(ab.length <2){
                                list.add(key);
                            }
						}
						if(list.size() <1){
							
                        } else{
							
                            sendToAll(" "+list,"room");
                        }
                       
                    } else if(protocol.equals("room_list_join")){
                        Waiting_room.add(conToClient);
                    } else if(protocol.equals("room_break")){
						String key = msgs[1] ;
						sendToAll("delete",key);
                        room.remove(key);
                        System.out.println("room break , rooms left : " + room);
                    }
                    else if (protocol.equals("room_out")){
                        String key = msgs[1] ; //방의 이름
						room_out  = room.get(key); //나갈 방을 새로운 리스트에 담는다.
						room_out.remove(conToClient);
						room.put(key, room_out);
						System.out.println("room out, all room: " + room);
						sendToAll(msgs[2],"out");	//내 닉네임과 나간다고 알린다		
					}
					else if(protocol.equals("ID")){
						conToClient.Make_id(msgs[1]);
					}

                }
            } catch (Exception e) {
            }
        }

        public void sendToAll(String message, String key) throws IOException{
            List<ConnectionToClient> clients_chat = new ArrayList<>();
            clients_chat = room.get(key);
            if(key.equals("room")){                
                    System.out.println("Send room list to clients :" + message);
                    conToClient.write_sec(message);
                
			}else if (message.equals("delete")){
				for(ConnectionToClient client :clients_chat){
                    System.out.println("room delete");
                    client.write_sec("delete");
            }
			}else if (key.equals("out")){
				for(ConnectionToClient client :clients_chat){
                    System.out.println("room out");
					client.write_sec("out|"+message);
				}
            }else if (key.equals("join")){
				for(ConnectionToClient client :clients_chat){
                    System.out.println("room join");
                    client.write_sec("join|"+message);
			}
		}
			else {
                for(ConnectionToClient client :clients_chat){
                    System.out.println("message: " + message);
                    client.write_sec(message);
            }

            }


        }
    }


    static class ConnectionToClient {
        Socket socket;
        BufferedReader br;
        DataOutputStream dos;
		String ID;

        ConnectionToClient(Socket socket) {
            this.socket = socket;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                dos = new DataOutputStream(socket.getOutputStream());
            } catch (Exception e) {
                System.out.println(e);
            }
        }
        public String read(){
            try{
				
                return br.readLine();
            }catch(Exception e){
                System.out.println(e);
                return null;
            }
        }

        public void write_sec(String msg) {
            try {
                dos.writeBytes(msg);
                dos.flush();
            } catch (Exception e) {
                System.out.println(e);
            }
		}
		public void Make_id(String id) {
            try {
                ID = id;
            } catch (Exception e) {
                System.out.println(e);
            }
		}

    }




}


