package org.yacos.web.author.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.ModelAndViewDefiningException;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
import org.yacos.core.article.Article;
import org.yacos.core.article.IArticleManager;
import org.yacos.core.conferences.Conference;
import org.yacos.core.users.User;
import org.yacos.web.author.form.FormSubmission;
import org.yacos.web.system.session.SessionService;

public class SArticleController extends SimpleFormController {

	/** Logger for this class and subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	private IArticleManager articleManager;
	private String downloadDirPath;

	public ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
	throws ServletException, IllegalStateException {

		// Fetching conference
		Conference conf = SessionService.getInstance().getCurrentConference();
		
		// Fetching user
		User user = SessionService.getInstance().getCurrentUser();

		String title = ((FormSubmission) command).getTitle();
		String theme = ((FormSubmission) command).getTheme();
		String abstractText = ((FormSubmission) command).getAbstractText();

		ArrayList<String> listSecondaryAuthor = new ArrayList<String>();
		// Removes null entries from the list
		for(String sAuthor : ((FormSubmission) command).getListe()){
			if(sAuthor != null){
				listSecondaryAuthor.add(sAuthor);
			}
		}

		String action = request.getParameter("action");
		
		// We're creating a new article, in opposition of modifying one
		if (action == null || action.equals(""))
		{
			// Try to save the file
			String nomFile="";

			try {
				MultipartFile file = ((FormSubmission) command).getFile();
				// No file
				if (file == null || file.isEmpty()) {
					errors.rejectValue("file", "form.submitArticle.noFile");
					try {
						return showForm(request, response, errors);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}					
				else {
					// Checking the extension
					String extension = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 4).toLowerCase();
					logger.info("The file extension is: " + extension);

					boolean typePDF = conf.isTypePDF();
					boolean typeLatec = conf.isTypeLatec();
					boolean typeWord = conf.isTypeWord();
					boolean typeODT = conf.isTypeODT();
					boolean isOneSelected = false;
					boolean extensionTrue = false;
					String acceptedExt = "";

					if (typePDF || typeLatec || typeWord || typeODT)
						isOneSelected = true;

					if (isOneSelected) {
						if (typePDF) {
							acceptedExt = acceptedExt + ".pdf ";
							if (extension.equals(".pdf"))
								extensionTrue = true;
						}
						if (typeLatec) {
							acceptedExt = acceptedExt + ".tex ";
							if (extension.equals(".tex"))
								extensionTrue = true;
						}
						if (typeWord) {
							acceptedExt = acceptedExt + ".doc .docx ";
							String extension1 = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 4).toLowerCase();
							String extension2 = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 5).toLowerCase();
							if (extension1.equals(".doc"))
								extensionTrue = true;
							if (extension2.equals(".docx"))
								extensionTrue = true;
						}
						if (typeODT) {
							acceptedExt = acceptedExt + ".odt";
							if (extension.equals(".odt"))
								extensionTrue = true;
						}
						if (! extensionTrue) {
							errors.rejectValue("file", null, "The file's extensions allowed are the following: " + acceptedExt);
							try {
								return showForm(request, response, errors);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}

					// Actually creates the article
					Article newArticle = articleManager.addArticle(
							title, theme, abstractText, nomFile, user.getLogin(),
							listSecondaryAuthor, Article.State.SUBMITED, conf.getId());
					
					// We had a persistence error, stop and return
					if(newArticle==null){
						errors.reject("article.errors.didNotSave");
						try {
							return showForm(request, response, errors);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}

					byte b[] = file.getBytes();
					
					// Create the file name
					String path = "conference"+conf.getId()+"/";
					// Ensure we have the correct file hierarchy
					(new File(downloadDirPath+path)).mkdirs();
					// Complete the path so it is valid, relative to the JBoss working dir
					path += newArticle.getId()+"_"+file.getOriginalFilename();
					// Create the actual output file
					File uploadedFile = new File(downloadDirPath+path);
					// Write the data
					FileOutputStream fos = new FileOutputStream(uploadedFile);
					fos.write(b);
					fos.close();
					
					// Save the file URL in the database, now it's saved
					newArticle.setURL_article(path);
					articleManager.updateArticle(newArticle);
				}
			}

			catch (FileNotFoundException e) {
				System.out.println(e);
			} catch (IOException e) {
				System.out.println(e);
			}

			// The role author might have been added, refresh the credentials
			SessionService.getInstance().refreshAuthentication();
		}
		// Case of a modification of an existing article
		else if (action.equals("modify")) {
			String articleID = request.getParameter("articleID");

			try {
				Integer id = new Integer(articleID);

				Article old = articleManager.getArticle(id);
				// In case of an error, we want the secondary authors to be filled on the page
				request.setAttribute("listSecondaryAuthors", old.getSecondaryAuthors());
				old.setTitle(title);
				old.setTopic(theme);
				old.setSecondaryAuthors(listSecondaryAuthor);
				old.setAbstractText(abstractText);

				// Check that the user owns this article
				String login = SessionService.getInstance().getCurrentUserLogin();
				if(! old.getMainAuthor().getLogin().equals(login)){
					// Throw a denied page
					throw new ModelAndViewDefiningException(new ModelAndView("denied"));
				}

				MultipartFile file = ((FormSubmission) command).getFile();
				if (file == null || file.isEmpty()) {
					articleManager.updateArticle(old);
				}
				else {

					String extension = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 4).toLowerCase();
					logger.info("The file extension is: " + extension);

					boolean typePDF = conf.isTypePDF();
					boolean typeLatec = conf.isTypeLatec();
					boolean typeWord = conf.isTypeWord();
					boolean typeODT = conf.isTypeODT();
					boolean isOneSelected = false;
					boolean extensionTrue = false;
					String acceptedExt = "";

					if (typePDF || typeLatec || typeWord || typeODT)
						isOneSelected = true;

					if (isOneSelected) {
						if (typePDF) {
							acceptedExt = acceptedExt + ".pdf ";
							if (extension.equals(".pdf"))
								extensionTrue = true;
						}
						if (typeLatec) {
							acceptedExt = acceptedExt + ".tex ";
							if (extension.equals(".tex"))
								extensionTrue = true;
						}
						if (typeWord) {
							acceptedExt = acceptedExt + ".doc .docx ";
							String extension1 = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 4).toLowerCase();
							String extension2 = file.getOriginalFilename().substring(file.getOriginalFilename().length() - 5).toLowerCase();
							if (extension1.equals(".doc"))
								extensionTrue = true;
							if (extension2.equals(".docx"))
								extensionTrue = true;
						}
						if (typeODT) {
							acceptedExt = acceptedExt + ".odt";
							if (extension.equals(".odt"))
								extensionTrue = true;
						}
						if (! extensionTrue) {
							errors.rejectValue("file", null, "The file's extensions allowed are the following: " + acceptedExt);
							try {
								return showForm(request, response, errors);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}

					byte b[] = file.getBytes();

					String path = "conference"+conf.getId()+"/";
					(new File(downloadDirPath+path)).mkdirs();
					path += old.getId()+"_"+file.getOriginalFilename();
					File uploadedFile = new File(downloadDirPath+path);

					FileOutputStream fos = new FileOutputStream(uploadedFile);

					fos.write(b);
					fos.close();

					old.setURL_article(path);
					articleManager.updateArticle(old);

				}
			} catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			} catch (FileNotFoundException e) {
				System.out.println(e);
			} catch (IOException e) {
				System.out.println(e);
			}

		}
		else {
			throw new ModelAndViewDefiningException(new ModelAndView("404error"));
		}

		return new ModelAndView(new RedirectView(getSuccessView()));
	}

	protected Object formBackingObject(HttpServletRequest request) throws ModelAndViewDefiningException {
		String action = request.getParameter("action");
		
		// date verification 
		Conference conf = SessionService.getInstance().getCurrentConference();
		
		if(conf == null){
			throw new ModelAndViewDefiningException(new ModelAndView("main"));
		}
		
		if(conf.getDateArticle().before(new Date())){
			throw new ModelAndViewDefiningException(new ModelAndView("main","end","submission"));
		}
		
		
		if (action == null || action.equals(""))
		{
			FormSubmission myArticle = new FormSubmission();
			return myArticle;
		}
		else if (action.equals("modify")) {

			String articleID = request.getParameter("articleID");

			try {
				Integer id = new Integer(articleID);

				Article a = articleManager.getArticle(id);

				if (a == null)
					throw new ModelAndViewDefiningException(new ModelAndView("denied", "message", getMessageSourceAccessor().getMessage("submission.modify.denied")));
				// Check that the user owns this article
				String login = SessionService.getInstance().getCurrentUserLogin();
				if(! a.getMainAuthor().getLogin().equals(login)){
					throw new ModelAndViewDefiningException(new ModelAndView("denied"));
				}
				
				FormSubmission myArticle = new FormSubmission();				

				myArticle.setAbstractText(a.getAbstractText());
				myArticle.setTitle(a.getTitle());
				//myArticle.setListe(a.getSecondaryAuthors());
				myArticle.setTheme(a.getTopic());
				
				request.setAttribute("listSecondaryAuthors", a.getSecondaryAuthors());
				
				return myArticle;

			}
			catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			}

		}
		else {
			throw new ModelAndViewDefiningException(new ModelAndView("404error"));
		}


	}

	public IArticleManager getArticleManager() {
		return articleManager;
	}

	public void setArticleManager(IArticleManager articleManager) {
		this.articleManager = articleManager;
	}

	public String getDownloadDirPath() {
		return downloadDirPath;
	}

	public void setDownloadDirPath(String downloadDirPath) {
		this.downloadDirPath = downloadDirPath;
	}
}