package CHAPTER14;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.util.List;

// 클라이언트 GUI  클래스
class ChatClientGUI extends JFrame implements ActionListener, Runnable {
	private String serverAddress; // 서버 주소
	private String username; // 사용자 이름
	private Socket clientSocket; // 클라이언트 소켓
	private BufferedReader inputReader; // 서버로부터 입력 받는 스트림
	private PrintWriter outputWriter; // 서버로 출력하는 스트림
	private JTextArea chatDisplayArea; // 채팅 메시지 출력 영역
	private JTextField messageField, usernameField; // 메시지 입력 필드, 사용자 이름 필드
	private JButton loginButton, logoutButton, exitButton; // 버튼들
	private JPanel topControlPanel, bottomControlPanel; // GUI 영역 구성 패널
	private CardLayout viewSwitcher; // 로그인/로그아웃 화면 전환
	private JPanel viewPanel; // 카드 레이아웃에 사용될 뷰 패널
	private boolean connectionActive = false; // 연결 상태 확인용
	private Thread listenerThread; // 서버로부터 메시지 수신하는 쓰레드

	// 생성자: GUI 구성
	public ChatClientGUI(String serverAddress) {
		this.serverAddress = serverAddress;

		setTitle("멀티 채팅 클라이언트");
		setSize(500, 400);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new BorderLayout());

		// 채팅창 출력 영역 설정
		chatDisplayArea = new JTextArea();
		chatDisplayArea.setEditable(false);
		add(new JScrollPane(chatDisplayArea), BorderLayout.CENTER);

		// 메시지 입력창과 종료 버튼 구성
		messageField = new JTextField();
		messageField.addActionListener(this);

		exitButton = new JButton("종료");
		exitButton.addActionListener(this);

		bottomControlPanel = new JPanel(new BorderLayout());
		bottomControlPanel.add(messageField, BorderLayout.CENTER);
		bottomControlPanel.add(exitButton, BorderLayout.EAST);
		add(bottomControlPanel, BorderLayout.SOUTH);

		// 로그인/로그아웃 버튼 설정
		loginButton = new JButton("로그인");
		logoutButton = new JButton("로그아웃");
		loginButton.addActionListener(this);
		logoutButton.addActionListener(this);

		usernameField = new JTextField(10);

		// 로그인 화면
		JPanel loginPanel = new JPanel(new FlowLayout());
		loginPanel.add(new JLabel("대화명: "));
		loginPanel.add(usernameField);
		loginPanel.add(loginButton);

		// 로그아웃 화면
		JPanel logoutPanel = new JPanel(new FlowLayout());
		logoutPanel.add(new JLabel("로그아웃됨: "));
		logoutPanel.add(logoutButton);

		// 카드 레이아웃에 화면 두 개 등록
		viewPanel = new JPanel();
		viewSwitcher = new CardLayout();
		viewPanel.setLayout(viewSwitcher);
		viewPanel.add(loginPanel, "LOGIN");
		viewPanel.add(logoutPanel, "LOGOUT");
		add(viewPanel, BorderLayout.NORTH);

		viewSwitcher.show(viewPanel, "LOGIN"); // 초기 화면은 로그인
		setVisible(true);
	}

	// 서버 연결 메서드
	private void establishConnection() {
		try {
			clientSocket = new Socket(serverAddress, 8000); // 서버에 연결
			outputWriter = new PrintWriter(clientSocket.getOutputStream(), true);
			inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			outputWriter.println(username + "/login"); // 로그인 메시지 전송
			connectionActive = true;
			listenerThread = new Thread(this); // 메시지 수신 스레드 시작
			listenerThread.start();
			chatDisplayArea.append("[시스템] 서버에 연결됨\n");
		} catch (IOException e) {
			chatDisplayArea.append("[오류] 서버 연결 실패\n");
		}
	}

	// 버튼 및 입력창 이벤트 처리
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();

		if (source == exitButton) {
			System.exit(0); // 종료 버튼 클릭 시 프로그램 종료
		} else if (source == loginButton) {
			username = usernameField.getText().trim();
			if (!username.isEmpty()) {
				viewSwitcher.show(viewPanel, "LOGOUT"); // 화면 전환
				establishConnection(); // 서버 연결
			}
		} else if (source == logoutButton) {
			outputWriter.println(username + "/logout"); // 로그아웃 메시지 전송
			chatDisplayArea.setText("");
			viewSwitcher.show(viewPanel, "LOGIN");
			connectionActive = false;
			try {
				inputReader.close();
				outputWriter.close();
				clientSocket.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		} else if (source == messageField) {
			String message = messageField.getText().trim();
			if (!message.isEmpty()) {
				outputWriter.println(username + "/" + message); // 메시지 전송
				messageField.setText(""); // 입력창 초기화
			}
		}
	}

	// 서버로부터 메시지 수신 스레드
	public void run() {
		String incomingMessage;
		try {
			while (connectionActive && (incomingMessage = inputReader.readLine()) != null) {
				String[] parts = incomingMessage.split("/");
				chatDisplayArea.append(parts[0] + ": " + parts[1] + "\n");
			}
		} catch (IOException e) {
			chatDisplayArea.append("[시스템] 연결 종료\n");
		}
	}
}

// 서버 클래스
class ChatServer {
	private ServerSocket chatServerSocket;
	private final List<ClientHandler> connectedClients = new ArrayList<>();

	// 서버 실행 메서드
	public void startServer() {
		try {
			chatServerSocket = new ServerSocket(8000); // 포트 8000으로 서버 오픈
			System.out.println("[서버 시작됨] 포트 8000");
			while (true) {
				Socket newClientSocket = chatServerSocket.accept();
				ClientHandler clientHandler = new ClientHandler(newClientSocket);
				connectedClients.add(clientHandler); // 클라이언트 리스트에 추가
				clientHandler.start(); // 스레드로 실행
			}
		} catch (IOException e) {
			System.out.println("[서버 오류] " + e.getMessage());
		}
	}

	// 모든 클라이언트에게 메시지 전송
	private void broadcastMessage(String message) {
		for (ClientHandler client : connectedClients) {
			client.sendMessage(message);
		}
	}

	// 클라이언트 처리 클래스
	class ClientHandler extends Thread {
		private Socket handlerSocket;
		private PrintWriter clientOut;
		private BufferedReader clientIn;
		private String clientUsername;

		public ClientHandler(Socket socket) {
			this.handlerSocket = socket;
		}

		public void run() {
			try {
				clientOut = new PrintWriter(handlerSocket.getOutputStream(), true);
				clientIn = new BufferedReader(new InputStreamReader(handlerSocket.getInputStream()));
				String receivedMessage;

				while ((receivedMessage = clientIn.readLine()) != null) {
					String[] tokens = receivedMessage.split("/");
					clientUsername = tokens[0];
					String command = tokens[1];

					if ("login".equals(command)) {
						broadcastMessage("서버/" + clientUsername + "님이 입장했습니다.");
					} else if ("logout".equals(command)) {
						broadcastMessage("서버/" + clientUsername + "님이 퇴장했습니다.");
						connectedClients.remove(this); // 클라이언트 제거
						break;
					} else {
						broadcastMessage(receivedMessage); // 일반 메시지
					}
				}
			} catch (IOException e) {
				connectedClients.remove(this);
				System.out.println("[클라이언트 연결 종료] " + clientUsername);
			}
		}

		// 클라이언트에게 메시지 전송
		public void sendMessage(String msg) {
			clientOut.println(msg);
		}
	}
}

// 메인 클래스
public class REAL_MultiChat {
	public static void main(String[] args) {
		// 서버를 실행하려면 아래 줄의 주석을 해제
		//new ChatServer().startServer(); // 1. 서버 실행

		// 클라이언트 실행(서버 실행 후 사용)
		new ChatClientGUI("127.0.0.1"); // 2. 클라이언트 실행
	}
}

//
////필요한 라이브러리 import
//import java.awt.*; // GUI 관련 클래스 (AWT)
//import java.awt.event.*; // 이벤트 처리
//import java.io.*; // 입출력 스트림
//import java.net.*; // 네트워크 관련
//import java.util.*; // 유틸리티 클래스
//import javax.swing.*; // 스윙 GUI 컴포넌트
//import java.util.List; // List 인터페이스
//
////클라이언트 GUI 클래스
//class ChatClientGUI extends JFrame implements ActionListener, Runnable {
//	private String serverAddress; // 서버 주소
//	private String username; // 사용자 이름
//	private Socket clientSocket; // 클라이언트 소켓
//	private BufferedReader inputReader; // 서버로부터 입력 받는 스트림
//	private PrintWriter outputWriter; // 서버로 출력하는 스트림
//	private JTextArea chatDisplayArea; // 채팅 메시지 출력 영역
//	private JTextField messageField, usernameField; // 메시지 입력 필드, 사용자 이름 필드
//	private JButton loginButton, logoutButton, exitButton; // 버튼들
//	private JPanel topControlPanel, bottomControlPanel; // GUI 영역 구성 패널
//	private CardLayout viewSwitcher; // 로그인/로그아웃 화면 전환
//	private JPanel viewPanel; // 카드 레이아웃에 사용될 뷰 패널
//	private boolean connectionActive = false; // 연결 상태 확인용
//	private Thread listenerThread; // 서버로부터 메시지 수신하는 쓰레드
//
//	// 생성자: GUI 구성
//	public ChatClientGUI(String serverAddress) {
//		this.serverAddress = serverAddress;
//
//		setTitle("멀티 채팅 클라이언트");
//		setSize(500, 400);
//		setDefaultCloseOperation(EXIT_ON_CLOSE);
//		setLayout(new BorderLayout());
//
//		// 채팅창 출력 영역 설정
//		chatDisplayArea = new JTextArea();
//		chatDisplayArea.setEditable(false);
//		add(new JScrollPane(chatDisplayArea), BorderLayout.CENTER);
//
//		// 메시지 입력창과 종료 버튼 구성
//		messageField = new JTextField();
//		messageField.addActionListener(this);
//
//		exitButton = new JButton("종료");
//		exitButton.addActionListener(this);
//
//		bottomControlPanel = new JPanel(new BorderLayout());
//		bottomControlPanel.add(messageField, BorderLayout.CENTER);
//		bottomControlPanel.add(exitButton, BorderLayout.EAST);
//		add(bottomControlPanel, BorderLayout.SOUTH);
//
//		// 로그인/로그아웃 버튼 설정
//		loginButton = new JButton("로그인");
//		logoutButton = new JButton("로그아웃");
//		loginButton.addActionListener(this);
//		logoutButton.addActionListener(this);
//
//		usernameField = new JTextField(10);
//
//		// 로그인 화면
//		JPanel loginPanel = new JPanel(new FlowLayout());
//		loginPanel.add(new JLabel("대화명: "));
//		loginPanel.add(usernameField);
//		loginPanel.add(loginButton);
//
//		// 로그아웃 화면
//		JPanel logoutPanel = new JPanel(new FlowLayout());
//		logoutPanel.add(new JLabel("로그아웃됨: "));
//		logoutPanel.add(logoutButton);
//
//		// 카드 레이아웃에 화면 두 개 등록
//		viewPanel = new JPanel();
//		viewSwitcher = new CardLayout();
//		viewPanel.setLayout(viewSwitcher);
//		viewPanel.add(loginPanel, "LOGIN");
//		viewPanel.add(logoutPanel, "LOGOUT");
//		add(viewPanel, BorderLayout.NORTH);
//
//		viewSwitcher.show(viewPanel, "LOGIN"); // 초기 화면은 로그인
//		setVisible(true);
//	}
//
//	// 서버 연결 메서드
//	private void establishConnection() {
//		try {
//			clientSocket = new Socket(serverAddress, 8000); // 서버에 연결
//			outputWriter = new PrintWriter(clientSocket.getOutputStream(), true);
//			inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//			outputWriter.println(username + "/login"); // 로그인 메시지 전송
//			connectionActive = true;
//			listenerThread = new Thread(this); // 메시지 수신 쓰레드 시작
//			listenerThread.start();
//			chatDisplayArea.append("[시스템] 서버에 연결됨\n");
//		} catch (IOException e) {
//			chatDisplayArea.append("[오류] 서버 연결 실패\n");
//		}
//	}
//
//	// 버튼 및 입력창 이벤트 처리
//	public void actionPerformed(ActionEvent e) {
//		Object source = e.getSource();
//
//		if (source == exitButton) {
//			System.exit(0); // 종료 버튼 클릭 시 프로그램 종료
//		} else if (source == loginButton) {
//			username = usernameField.getText().trim();
//			if (!username.isEmpty()) {
//				viewSwitcher.show(viewPanel, "LOGOUT"); // 화면 전환
//				establishConnection(); // 서버 연결
//			}
//		} else if (source == logoutButton) {
//			outputWriter.println(username + "/logout"); // 로그아웃 메시지 전송
//			chatDisplayArea.setText("");
//			viewSwitcher.show(viewPanel, "LOGIN");
//			connectionActive = false;
//			try {
//				inputReader.close();
//				outputWriter.close();
//				clientSocket.close();
//			} catch (IOException ex) {
//				ex.printStackTrace();
//			}
//		} else if (source == messageField) {
//			String message = messageField.getText().trim();
//			if (!message.isEmpty()) {
//				outputWriter.println(username + "/" + message); // 메시지 전송
//				messageField.setText(""); // 입력창 초기화
//			}
//		}
//	}
//
//	// 서버로부터 메시지 수신 쓰레드
//	public void run() {
//		String incomingMessage;
//		try {
//			while (connectionActive && (incomingMessage = inputReader.readLine()) != null) {
//				String[] parts = incomingMessage.split("/");
//				chatDisplayArea.append(parts[0] + ": " + parts[1] + "\n");
//			}
//		} catch (IOException e) {
//			chatDisplayArea.append("[시스템] 연결 종료\n");
//		}
//	}
//}
//
////서버 클래스
//class ChatServer {
//	private ServerSocket chatServerSocket;
//	private final List<ClientHandler> connectedClients = new ArrayList<>();
//
//	// 서버 실행 메서드
//	public void startServer() {
//		try {
//			chatServerSocket = new ServerSocket(8000); // 포트 8000으로 서버 오픈
//			System.out.println("[서버 시작됨] 포트 8000");
//			while (true) {
//				Socket newClientSocket = chatServerSocket.accept(); // 새 클라이언트 수락
//				ClientHandler clientHandler = new ClientHandler(newClientSocket);
//				connectedClients.add(clientHandler); // 클라이언트 리스트에 추가
//				clientHandler.start(); // 쓰레드로 실행
//			}
//		} catch (IOException e) {
//			System.out.println("[서버 오류] " + e.getMessage());
//		}
//	}
//
//	// 모든 클라이언트에게 메시지 전송
//	private void broadcastMessage(String message) {
//		for (ClientHandler client : connectedClients) {
//			client.sendMessage(message);
//		}
//	}
//
//	// 클라이언트 처리 클래스
//	class ClientHandler extends Thread {
//		private Socket handlerSocket;
//		private PrintWriter clientOut;
//		private BufferedReader clientIn;
//		private String clientUsername;
//
//		public ClientHandler(Socket socket) {
//			this.handlerSocket = socket;
//		}
//
//		public void run() {
//			try {
//				clientOut = new PrintWriter(handlerSocket.getOutputStream(), true);
//				clientIn = new BufferedReader(new InputStreamReader(handlerSocket.getInputStream()));
//				String receivedMessage;
//
//				while ((receivedMessage = clientIn.readLine()) != null) {
//					String[] tokens = receivedMessage.split("/");
//					clientUsername = tokens[0];
//					String command = tokens[1];
//
//					if ("login".equals(command)) {
//						broadcastMessage("서버/" + clientUsername + "님이 입장했습니다.");
//					} else if ("logout".equals(command)) {
//						broadcastMessage("서버/" + clientUsername + "님이 퇴장했습니다.");
//						connectedClients.remove(this); // 클라이언트 제거
//						break;
//					} else {
//						broadcastMessage(receivedMessage); // 일반 메시지
//					}
//				}
//			} catch (IOException e) {
//				connectedClients.remove(this);
//				System.out.println("[클라이언트 연결 종료] " + clientUsername);
//			}
//		}
//
//		// 클라이언트에게 메시지 전송
//		public void sendMessage(String msg) {
//			clientOut.println(msg);
//		}
//	}
//}
//
////메인 클래스
//public class REAL_MultiChat {
//	public static void main(String[] args) {
//		// 서버를 실행하려면 아래 줄의 주석을 해제
//		new ChatServer().startServer(); // 1. 서버 실행
//
//		// 클라이언트 실행 (서버 실행 후 사용)
//		new ChatClientGUI("127.0.0.1"); // 2. 클라이언트 실행
//	}
//}
