package fr.insa.clavardator.lib.message;

import fr.insa.clavardator.lib.users.User;
import fr.insa.clavardator.lib.users.UserInformation;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

public class FileMessage extends Message {
	public static final long MAX_FILE_SIZE = 20 * 1024 * 1024; // 20 Mo
	public static final String STORED_FILES_FOLDER = "clavardator_stored_files";

	private final String fileName;
	byte[] rawFile = null;
	private String path;

	/**
	 * Constructs a FileMessage
	 *
	 * @param sender    The sender of the message
	 * @param recipient The recipient of the message
	 * @param date      The sending date of the message
	 * @param text      The text of the message
	 * @param filePath  The path to the file
	 * @throws IOException If the file does not exist, is not readable, is not a file, or is too large
	 */
	public FileMessage(UserInformation sender, UserInformation recipient, Date date, String text, String filePath) throws IOException {
		super(sender, recipient, date, text);

		File file = new File(filePath);
		if (!file.exists())
			throw new IOException("The file " + file.getAbsolutePath() + " does not exist");
		if (!file.canRead())
			throw new IOException("The file " + file.getAbsolutePath() + " is not readable");
		if (!file.isFile())
			throw new IOException("The path " + file.getAbsolutePath() + " does not lead to a file");
		if (file.length() > MAX_FILE_SIZE)
			throw new IOException("The file " + file.getAbsolutePath() + " is too large");

		fileName = file.getName();
		path = filePath;
	}

	public FileMessage(User sender, User recipient, Date date, String text, String filePath) throws IOException {
		this(new UserInformation(sender), new UserInformation(recipient), date, text, filePath);
	}

	public String getFileName() {
		return fileName;
	}

	public String getPath() {
		return path;
	}

	/**
	 * Stores the file in the clavardator directory.
	 * The field {@code path} is then updated to point to the new location.
	 *
	 * @return the path to the file
	 */
	public String storeFile() throws IOException {

		// Create clavardator directory
		File dir = new File(STORED_FILES_FOLDER);
		dir.mkdirs();

		// Copy the source file to rawFile
		if (rawFile == null) {
			FileInputStream istream = new FileInputStream(path);
			rawFile = istream.readAllBytes();
			istream.close();
		}

		path = STORED_FILES_FOLDER + File.separatorChar + fileName;

		// Create new file
		int extensionBeginning = fileName.lastIndexOf('.');
		String name = fileName;
		String extension = "";
		if (extensionBeginning != -1) {
			name = fileName.substring(0, extensionBeginning);
			extension = fileName.substring(extensionBeginning);
		}
		File file = new File(path);
		int suffix = 1;
		while (!file.createNewFile()) {
			path = STORED_FILES_FOLDER + File.separatorChar + name + "_" + suffix++ + extension;
			file = new File(path);
		}

		// Write the file in clavardator dir
		FileOutputStream ostream = new FileOutputStream(file);
		ostream.write(rawFile);
		ostream.close();
		return path;
	}
}