import java.io.*;
import java.net.*;
import java.util.*;

class User implements Runnable
{
	Socket socket = null;
	BufferedReader br = null;
	BufferedWriter bw = null;
	Vector UserList = null;

	String UserId = null;
	String UserPasswd = null;
	String UserRealName = null;
	String UserEmail = null;
	String UserLastLogin = null;
	long UserPerm = 0;

	User(Socket socket,Vector UserList)
	{
		this.socket = socket;
		this.UserList = UserList;

		try
		{
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		}
		catch(IOException e){}
	}

	public void run()
	{
		if(login())
			Main();
		logout();
	}

	public boolean login()
	{
		Date date = new Date();
		showFile(Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "welcome");
		IO.outputln("歡迎光臨 " + Config.BBSNAME,bw);
		IO.outputln("現在線上有 [" + UserList.size() + "] 人",bw);
		for(int i = 0;i < 3;i++)
		{
			IO.outputln("註冊請用 new ,參觀請用 guest",bw);
			IO.output("Your ID : ",bw);
			UserId = IO.input(br,bw);
			IO.outputln("",bw);

			if(UserId.equalsIgnoreCase("new"))
			{
				newUser();
				UserList.addElement(this);
				IO.outputFile(date + " " + UserId + " login from " + socket + "\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "log");
				UserLastLogin = date.toString();
				return true;
			}
			else if(UserId.equalsIgnoreCase("guest"))
			{
				UserId = "guest";
				UserPerm = Perm.GUEST;
				UserList.addElement(this);
				IO.outputFile(date + " " + UserId + " login from " + socket + "\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "log");
				UserLastLogin = date.toString();
				return true;
			}
			else
			{
				if(!Util.isIdUsed(UserId))
				{
					IO.outputln("對不起 ,這個代號是錯誤的",bw);
					continue;
				}

				IO.output("Your Passwd : ",bw);
				UserPasswd = IO.inputPass(br,bw);
				IO.outputln("",bw);
				if(Util.checkPasswd(UserId,UserPasswd))
				{
					UserPerm = Util.getPerm(UserId);
					UserList.addElement(this);
					IO.outputFile(date + " " + UserId + " login from " + socket + "\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "log");
					UserLastLogin = date.toString();
					return true;
				}
				else
				{
					IO.outputln("密碼錯誤",bw);
				}
			}
		}
		UserId = null;
		return false;
	}

	public void logout()
	{
		Date date = new Date();
		showFile(Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "bye");
		if(UserId == null)
		{
			IO.outputFile(date + " login failed from" + socket + "\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "log");
		}
		else
		{
			IO.outputFile(date + " " + UserId + " logout\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "log");
			IO.outputFile(UserLastLogin + " from " + socket + "\n",Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase() + File.separatorChar + "log");
		}
		for(int i = 0;i < UserList.size();i++)
		{
			if(((User)(UserList.elementAt(i))).socket == socket)
				UserList.removeElementAt(i);
		}
		try
		{
			socket.close();
		}
		catch(IOException e){}
	}

	public void newUser()
	{
		String temp;
		while(true)
		{
			IO.output("請輸入您想用的 ID : ",bw);
			UserId = IO.input(br,bw);
			IO.outputln("",bw);
			if(UserId.length() == 0)
				continue;
			if(Util.isIdUsed(UserId))
			{
				IO.outputln("對不起 ,這個 ID 已經有人用過了 ,請換一個試試",bw);
				continue;
			}
			break;
		}
		while(true)
		{
			IO.output("請輸入您想用的密碼 : ",bw);
			UserPasswd = IO.inputPass(br,bw);
			IO.outputln("",bw);
			if(UserPasswd.length() == 0)
				continue;
			IO.output("請再輸入您的密碼以便確認 : ",bw);
			temp = IO.inputPass(br,bw);
			IO.outputln("",bw);
			if(UserPasswd.equals(temp))
				break;
			IO.outputln("密碼不符,再來一次",bw);
		}

		do
		{
			IO.output("請輸入您的真實姓名 : ",bw);
			UserRealName = IO.input(br,bw);
			IO.outputln("",bw);
		}while(UserRealName.length() == 0);

		do
		{
			IO.output("請輸入您的 Email Address : ",bw);
			UserEmail = IO.input(br,bw);
			IO.outputln("",bw);
		}while(UserEmail.length() == 0);

		UserPerm = Perm.USER;

		Util.addUser(UserId,UserPasswd,UserPerm);

		Util.mkdir(Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase());
		IO.outputFile("歡迎光臨\n",Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase() + File.separatorChar + "index");
		IO.outputFile("歡迎光臨",Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase() + File.separatorChar + "歡迎光臨");
		IO.outputNewFile(UserRealName + "\n" + UserEmail + "\n",Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase() + File.separatorChar + "info");
	}

	public void Main()
	{
		String command = null;
		while(true)
		{
			IO.output(">",bw);
			command = IO.input(br,bw);
			IO.outputln("",bw);
			if(Run(command))
				break;
		}
	}

	public boolean Run(String command)
	{
		if(command.equalsIgnoreCase("logout"))
			return true;

		if(command.equalsIgnoreCase("setInfo"))
			setInfo();
		else if(command.equalsIgnoreCase("showUserList"))
			showUserList();
		else if(command.equalsIgnoreCase("write"))
			write();
		else if(command.equalsIgnoreCase("query"))
			query();
		else if(command.equalsIgnoreCase("showBoardList"))
			showBoardList();
		else if(command.equalsIgnoreCase("read"))
			read();
		else if(command.equalsIgnoreCase("post"))
			post();
		else if(command.equalsIgnoreCase("kill"))
			kill();
		else if(command.equalsIgnoreCase("newBoard"))
			newBoard();
		else if(command.equalsIgnoreCase("help") || command.equalsIgnoreCase("?"))
			showhelp();
		else
			IO.outputln("?",bw);

		return false;
	}

	public void showFile(String FileName)
	{
		String temp;
		BufferedReader in = IO.inputFile(FileName);
		try
		{
			while((temp = in.readLine()) != null)
			{
				IO.outputln(temp,bw);
			}
			in.close();
		}
		catch(IOException e){}
	}

	public void showhelp()
	{
/*
		IO.outputln("---------------------------------------------",bw);
		IO.outputln("setInfo			設定個人資料",bw);
		IO.outputln("---------------------------------------------",bw);
		IO.outputln("showUserList		傳送訊息",bw);
		IO.outputln("write			傳送訊息",bw);
		IO.outputln("query			查詢使用者",bw);
		IO.outputln("---------------------------------------------",bw);
		IO.outputln("showBoardList		文章列表",bw);
		IO.outputln("read			閱\讀文章",bw);
		IO.outputln("post			發表文章",bw);
		IO.outputln("---------------------------------------------",bw);
		IO.outputln("kill			踢人",bw);
		IO.outputln("newBoard		成立新版",bw);
		IO.outputln("---------------------------------------------",bw);
		IO.outputln("logout			離線",bw);
		IO.outputln("---------------------------------------------",bw);
*/
	}

	public void showMessage(String Message)
	{
		IO.outputln(Message,bw);
	}

	public void setInfo()
	{
		String temp,temp1;

		if(!Util.hasPerm(Perm.USER,UserPerm))
		{
			IO.outputln("對不起 ,你的權限不足",bw);
			return;
		}

		IO.output("請輸入密碼確認 : ",bw);
		temp = IO.inputPass(br,bw);
		IO.outputln("",bw);

		if(!temp.equals(UserPasswd))
		{
			IO.outputln("對不起 ,密碼錯誤",bw);
			return;
		}

		while(true)
		{
			IO.output("請輸入您想用的密碼 : ",bw);
			temp = IO.inputPass(br,bw);
			IO.outputln("",bw);
			if(temp.length() == 0)
				break;
			IO.output("請再輸入您的密碼以便確認 : ",bw);
			temp1 = IO.inputPass(br,bw);
			IO.outputln("",bw);
			if(temp.equals(temp1))
			{
				UserPasswd = temp;
				Util.addUser(UserId,UserPasswd,UserPerm);
				break;
			}
			IO.outputln("密碼不符,再來一次",bw);
		}

		do
		{
			IO.output("請輸入新的真實姓名 : ",bw);
			UserRealName = IO.input(br,bw);
			IO.outputln("",bw);
		}while(UserRealName.length() == 0);

		do
		{
			IO.output("請輸入新的 Email Address : ",bw);
			UserEmail = IO.input(br,bw);
			IO.outputln("",bw);
		}while(UserEmail.length() == 0);


		IO.outputNewFile(UserRealName + "\n" + UserEmail,Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase() + File.separatorChar + "info");
	}

	public void showUserList()
	{
		IO.outputln("UserList",bw);
		for(int i = 0;i < UserList.size();i++)
		{
			IO.outputln(i + " " + ((User)(UserList.elementAt(i))).UserId,bw);
		}
	}
	public void write()
	{
		String Name,Message;

		if(!Util.hasPerm(Perm.USER,UserPerm))
		{
			IO.outputln("對不起 ,你的權限不足",bw);
			return;
		}

		IO.output("To : ",bw);
		Name = IO.input(br,bw);
		IO.outputln("",bw);

		if(!Util.isIdUsed(Name))
		{
			IO.outputln("對不起 ,沒有這個人",bw);
			return;
		}

		if(!Util.isOnLine(Name,UserList))
		{
			IO.outputln("對不起 ,他不在線上",bw);
			return;
		}

		IO.output("Message : ",bw);
		Message = IO.input(br,bw);
		IO.outputln("",bw);

		for(int i = 0;i < UserList.size();i++)
		{
			if(((User)(UserList.elementAt(i))).UserId.equalsIgnoreCase(Name))
				((User)(UserList.elementAt(i))).showMessage(UserId + " : " + Message);
		}
	}

	public void query()
	{
		String Name;
		IO.output("Who : ",bw);
		Name = IO.input(br,bw);
		IO.outputln("",bw);

		if(!Util.isIdUsed(Name))
		{
			IO.outputln("對不起 ,沒有這個人",bw);
			return;
		}

		showFile(Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + Name.toLowerCase() + File.separatorChar + "info");
	}

	public void showBoardList()
	{
		showFile(Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "boards");
	}

	public void read()
	{
		BufferedReader in;
		String BoardName,FileName,Temp,TempPath;

		IO.output("版名 : ",bw);
		BoardName = IO.input(br,bw);
		IO.outputln("",bw);

		if(BoardName.length() == 0)
		{
			IO.outputln("對不起 ,沒有這個版",bw);
			return;
		}

		if(BoardName.equals("mbox"))
		{
			if(!Util.hasPerm(Perm.USER,UserPerm))
			{
				IO.outputln("對不起 ,你的權限不足",bw);
				return;
			}
			TempPath = Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + UserId.toLowerCase();
		}
		else if(Util.isBoardExit(BoardName))
			TempPath = Config.BBSHOME + File.separatorChar + "boards" + File.separatorChar + BoardName.toLowerCase();
		else
		{
			IO.outputln("對不起 ,沒有這個版",bw);
			return;
		}

		in = IO.inputFile(TempPath + File.separatorChar + "index");
		try
		{
			while((FileName = in.readLine()) != null)
				IO.outputln(FileName,bw);
			in.close();
		}
		catch(IOException e){}

		while(true)
		{
			IO.output("檔名 : ",bw);
			FileName = IO.input(br,bw);
			IO.outputln("",bw);

			if(FileName.length() == 0)
			{
				IO.outputln("對不起 ,檔名錯誤",bw);
				continue;
			}
			if(FileName.equals("!"))
				break;

			if(Util.isFileExists(TempPath + File.separatorChar + FileName))
			{
				in = IO.inputFile(TempPath + File.separatorChar + FileName);
				try
				{
					while((Temp = in.readLine()) != null)
						IO.outputln(Temp,bw);
					in.close();
				}
				catch(IOException e){}
			}
			else
				IO.outputln("檔案不存在",bw);
		}
	}

	public void post()
	{
		Date date;
		BufferedReader in;
		String BoardName,FileName,Temp,TempPath;

		if(!Util.hasPerm(Perm.USER,UserPerm))
		{
			IO.outputln("對不起 ,你的權限不足",bw);
			return;
		}

		IO.output("版名 : ",bw);
		BoardName = IO.input(br,bw);
		IO.outputln("",bw);

		if(BoardName.length() == 0)
		{
			IO.outputln("對不起 ,沒有這個版",bw);
			return;
		}

		if(Util.isIdUsed(BoardName))
			TempPath = Config.BBSHOME + File.separatorChar + "home" + File.separatorChar + BoardName.toLowerCase();
		else if(Util.isBoardExit(BoardName))
			TempPath = Config.BBSHOME + File.separatorChar + "boards" + File.separatorChar + BoardName.toLowerCase();
		else
		{
			IO.outputln("對不起 ,沒有這個版",bw);
			return;
		}

		while(true)
		{
			IO.output("檔名 : ",bw);
			FileName = IO.input(br,bw);
			IO.outputln("",bw);

			if(FileName.length() == 0)
			{
				IO.outputln("對不起 ,檔名錯誤",bw);
				continue;
			}

			if(FileName.equals("!"))
				return;

			if(!Util.isFileExists(TempPath + File.separatorChar + FileName))
			{
				IO.outputFile(FileName + "\n",TempPath + File.separatorChar + "index");
				break;
			}
			IO.outputln("檔案已存在",bw);
		}

		date = new Date();
		IO.outputFile(UserId + "\n" + date + "\n",TempPath + File.separatorChar + FileName);
		while(true)
		{
			Temp = IO.input(br,bw);
			IO.outputln("",bw);
			if(Temp.equals("."))
				break;
			IO.outputFile(Temp + "\n",TempPath + File.separatorChar + FileName);
		}
	}

	public void kill()
	{
		String Name;
		if(!Util.hasPerm(Perm.SYSOP,UserPerm))
		{
			IO.outputln("對不起 ,你的權限不足",bw);
			return;
		}

		IO.output("who : ",bw);
		Name = IO.input(br,bw);
		IO.outputln("",bw);

		if(!Util.isIdUsed(Name))
		{
			IO.outputln("對不起 ,沒有這個人",bw);
			return;
		}

		if(!Util.isOnLine(Name,UserList))
		{
			IO.outputln("對不起 ,他不在線上",bw);
			return;
		}

		for(int i = 0;i < UserList.size();i++)
		{
			if(((User)(UserList.elementAt(i))).UserId.equalsIgnoreCase(Name))
				((User)(UserList.elementAt(i))).logout();
		}
	}

	public void newBoard()
	{
		String BoardName;
		if(!Util.hasPerm(Perm.BOARDS,UserPerm))
		{
			IO.outputln("對不起 ,你的權限不足",bw);
			return;
		}

		IO.output("版名 : ",bw);
		BoardName = IO.input(br,bw);
		IO.outputln("",bw);
		if(Util.isFileExists(BoardName))
		{
			IO.outputln("對不起 ,該版已經存在了",bw);
			return;
		}

		Util.mkdir(Config.BBSHOME + File.separatorChar + "boards" + File.separatorChar + BoardName.toLowerCase());
		IO.outputFile(BoardName + "\n",Config.BBSHOME + File.separatorChar + "etc" + File.separatorChar + "boards");
		IO.outputFile("新版成立\n",Config.BBSHOME + File.separatorChar + "boards" + File.separatorChar + BoardName.toLowerCase() + File.separatorChar + "index");
		IO.outputFile("新版成立",Config.BBSHOME + File.separatorChar + "boards" + File.separatorChar + BoardName.toLowerCase() + File.separatorChar + "新版成立");
	}
}
