package authentication;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.TreeSet;

/**
 * \class Authentification
 * Provides an authentication manager implementation.
 */
@SuppressWarnings("serial")
public class Authentification implements AuthenticationManager, Serializable {
	private TreeSet<User> users = new TreeSet<User>();
	
	public void addUser(String login, String password) throws UserExistsException {
		users.add(new User(login, password));	// calls equals and compareTo
	}

	public void removeUser(String login) throws UserUnknownException {
		boolean removed = users.remove(new User(login, ""));
		if (!removed) {
			throw new UserUnknownException(login);
		}
	}
	
	public void authentify(String login, String password) throws UserUnknownException, WrongPasswordException {
		User tmpUser = new User(login, password);
		User user = users.ceiling(tmpUser);
		if (user.equals(tmpUser)) {
			if (user.getPassword().compareTo(password) != 0) {
				throw new WrongPasswordException(login);
			}
		} else {
			throw new UserUnknownException(login);
		}
	}
	
	public void save(String path) throws IOException {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			fos = new FileOutputStream(path);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(this);
		} finally {
			closeWriters(fos,oos);
		}
	}
	
	private void closeWriters(FileOutputStream fos, ObjectOutputStream oos) throws IOException {
		try {
			if (oos != null) {
				oos.close();
			}
		} finally {
			if (fos != null) {
				fos.close();
			}
		}
	}
	
	public static Authentification load(String path) throws IOException, ClassNotFoundException {
		Authentification aut = null;
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = new FileInputStream(path);
			ois = new ObjectInputStream(fis);
			aut = (Authentification) ois.readObject();
		} finally {
			closeReaders(fis, ois);
		}
		return aut;
	}
	
	private static void closeReaders(FileInputStream fis, ObjectInputStream ois) throws IOException {
		try {
			if (ois != null) {
				ois.close();
			}
		} finally {
			if (fis != null) {
				fis.close();
			}
		}
	}
}
