package isrp.model.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import isrp.hibernate.model.businessobject.Paper;
import isrp.hibernate.model.businessobject.User;
import isrp.hibernate.model.dao.PaperDao;
import isrp.hibernate.model.dao.UserDao;
import isrp.hibernate.model.dao.factory.DaoFactory;
import isrp.hibernate.model.util.FileUtil;
import isrp.hibernate.model.util.Md5HashCode;
import isrp.hibernate.model.util.email.EmailConfiguration;
import isrp.hibernate.model.util.email.EmailMessagesUtil;
import isrp.hibernate.model.util.email.EmailSender;
import isrp.model.service.PaperService;

public class PaperServiceImpl implements PaperService {
	private Log logger = LogFactory.getLog(this.getClass());

	public PaperServiceImpl() {

	}

	public boolean addPaper(Paper paper, User author,
			UploadedFile uploadedFile, String uploadPath,
			EmailConfiguration emailConfiguration) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		UserDao uDao = DaoFactory.getInstance().getUserDao();

		String uploadedFileName = uploadFile(uploadPath, uploadedFile);
		if (uploadedFileName != null) {
			paper.setPath(uploadedFileName);
			pDao.save(paper);
		} else {
			return false;
		}

		EmailSender eSender = new EmailSender(emailConfiguration);
		eSender.sendEMail(EmailMessagesUtil.newPaperMessageToAuthor(author,
				paper));
		eSender.sendEMail(EmailMessagesUtil.newPaperMessageToAdministrator(
				author, paper, uDao.getAdministratorEmail()));
		return true;
	}

	public boolean addPaperNewVersion(Paper paper, User author,
			UploadedFile uploadedFile, String uploadPath,
			EmailConfiguration emailConfiguration) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		UserDao uDao = DaoFactory.getInstance().getUserDao();

		if (deleteFile(uploadPath + '/' + paper.getPath())) {
			String uploadedFileName = uploadFile(uploadPath, uploadedFile);
			if (uploadedFileName != null) {
				paper.setPath(uploadedFileName);
				paper.setVersion(new Byte("2"));
				pDao.saveOrUpdate(paper);
			} else {
				return false;
			}
		} else {
			return false;
		}

		User reviewer = (User) uDao.findById(paper.getReviewerId());
		String adminEmail = uDao.getAdministratorEmail();

		EmailSender eSender = new EmailSender(emailConfiguration);
		eSender.sendEMail(EmailMessagesUtil.newPaperVersionMessage(author,
				paper, adminEmail, "Administrator"));
		eSender.sendEMail(EmailMessagesUtil.newPaperVersionMessage(author,
				paper, reviewer.getEmail(), reviewer.getFirstName() + " "
						+ reviewer.getLastName()));
		return true;
	}

	public void approvePaper(Paper paper, EmailConfiguration emailConfiguration) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		pDao.saveOrUpdate(paper);
		UserDao uDao = DaoFactory.getInstance().getUserDao();
		User author = (User) uDao.findById(paper.getAuthorId());
		EmailSender eSender = new EmailSender(emailConfiguration);
		eSender.sendEMail(EmailMessagesUtil.paperApprovedMessage(author));

	}

	public void assignReviewer(Paper paper, int reviewerId,
			EmailConfiguration emailConfiguration) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		UserDao uDao = DaoFactory.getInstance().getUserDao();
		pDao.saveOrUpdate(paper);

		// sending email
		User author = (User) uDao.findById(paper.getAuthorId());
		User reviewer = (User) uDao.findById(reviewerId);
		EmailSender eSender = new EmailSender(emailConfiguration);
		eSender.sendEMail(EmailMessagesUtil.assignReviewerMessageToReviewer(
				reviewer, paper));
		eSender.sendEMail(EmailMessagesUtil
				.assignReviewerMessageToAuthor(author));

	}

	public void delete(Paper paper) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		pDao.delete(paper);

	}

	public boolean deleteFile(String fileName) {
		// A File object to represent the filename
		File f = new File(fileName);

		// Make sure the file or directory exists and isn't write protected
		if (!f.exists())
			throw new IllegalArgumentException(
					"Delete: no such file or directory: " + fileName);

		if (!f.canWrite())
			throw new IllegalArgumentException("Delete: write protected: "
					+ fileName);

		// If it is a directory, make sure it is empty
		if (f.isDirectory()) {
			String[] files = f.list();
			if (files.length > 0)
				throw new IllegalArgumentException(
						"Delete: directory not empty: " + fileName);
		}

		// Attempt to delete it
		boolean success = f.delete();

		if (!success)
			throw new IllegalArgumentException("Delete: deletion failed");
		return success;

	}

	public Paper findById(int id) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		return (Paper) pDao.findById(id);

	}

	public List<Paper> getAllPapers(String sortColumn) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		return pDao.getAllPapers(sortColumn);
	}

	@Override
	public List<Paper> getAllPapers(String sortColumn, Integer userId,
			Integer role) {
		if (role == 1) {
			// admin
			return getAllPapers(sortColumn);
		} else if (role == 2) {
			// author
			return getAuthorPapers(userId, sortColumn);
		} else if (role == 3) {
			// reviewer
			return getReviewerPapers(userId, sortColumn);
		} else {
			return null;
		}
	}

	public List<Paper> getAuthorPapers(int userId, String sortColumn) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		return pDao.getUserPapers(userId, sortColumn);
	}

	public List<Paper> getReviewerPapers(int reviewerId, String sortColumn) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		return pDao.getReviewerPapers(reviewerId, sortColumn);
	}

	public void rejectPaper(Paper paper, EmailConfiguration emailConfiguration) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		pDao.saveOrUpdate(paper);
		UserDao uDao = DaoFactory.getInstance().getUserDao();
		User author = (User) uDao.findById(paper.getAuthorId());
		EmailSender eSender = new EmailSender(emailConfiguration);
		eSender.sendEMail(EmailMessagesUtil.paperRejectedMessage(author));
	}

	public void update(Paper paper) {
		PaperDao pDao = DaoFactory.getInstance().getPaperDao();
		pDao.saveOrUpdate(paper);
	}

	private String uploadFile(String path, UploadedFile uploadedFile) {
		try {
			PaperDao pDao = DaoFactory.getInstance().getPaperDao();
			String fileName = uploadedFile.getName();
			String fileExtension = fileName
					.substring(fileName.lastIndexOf('.'));
			logger.info("Upload:"
					+ fileName.substring(fileName.lastIndexOf('.')));
			Date date = new Date();
			String hash = Md5HashCode.getMd5HashCode(date.toString());
			while (pDao.checkIfPathExists(hash + fileExtension) != null) { // while
				// such file already exists
				date = new Date();
				hash = Md5HashCode.getMd5HashCode(date.toString());
			}
			String uploadedFileName = hash + fileExtension;

			File uniqueFile = FileUtil.uniqueFile(new File(path),
					uploadedFileName);
			FileUtil.write(uniqueFile, uploadedFile.getInputStream());
			return uploadedFileName;
		} catch (IOException e) {
			logger.error(e.getMessage(), e.getCause());
			return null;
		}
	}

}
