/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.servlet.outputhandler;

import static org.apache.openmeetings.util.OmFileHelper.bigImagePrefix;
import static org.apache.openmeetings.util.OmFileHelper.chatImagePrefix;
import static org.apache.openmeetings.util.OmFileHelper.profileImagePrefix;
import static org.apache.openmeetings.util.OmFileHelper.thumbImagePrefix;

import java.io.File;
import java.io.InputStream;

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

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.transaction.util.FileHelper;
import org.apache.openmeetings.converter.GenerateImage;
import org.apache.openmeetings.converter.GenerateThumbs;
import org.apache.openmeetings.data.file.FileProcessor;
import org.apache.openmeetings.db.dao.file.FileExplorerItemDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.file.FileExplorerItem;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.documents.GeneratePDF;
import org.apache.openmeetings.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.util.OmFileHelper;
import org.apache.openmeetings.util.OpenmeetingsVariables;
import org.apache.openmeetings.util.StoredFile;
import org.apache.openmeetings.util.process.ConverterProcessResultList;
import org.apache.openmeetings.util.process.UploadCompleteMessage;
import org.apache.openmeetings.util.stringhandlers.StringComparer;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class UploadController extends AbstractUploadController {
	private static final Logger log = Red5LoggerFactory.getLogger(
			UploadController.class, OpenmeetingsVariables.webAppRootKey);
	
	@Autowired
	private UserDao usersDao;
	@Autowired
	private ScopeApplicationAdapter scopeApplicationAdapter;
	@Autowired
	private GeneratePDF generatePDF;
	@Autowired
	private GenerateThumbs generateThumbs;
	@Autowired
	private GenerateImage generateImage;
	@Autowired
	private FileProcessor fileProcessor;
	@Autowired
	private FileExplorerItemDao fileExplorerItemDao;

	private String filesString[] = null;
	
    @RequestMapping(value = "/file.upload", method = RequestMethod.POST)
    public void handleFileUpload(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException {
    	UploadInfo info = validate(request, false);
    	try {
			String room_idAsString = request.getParameter("room_id");
			if (room_idAsString == null) {
				throw new ServletException("Missing Room ID");
			}
	
			Long room_id_to_Store = Long.parseLong(room_idAsString);
	
			String isOwnerAsString = request.getParameter("isOwner");
			if (isOwnerAsString == null) {
				throw new ServletException("Missing isOwnerAsString");
			}
			boolean isOwner = false;
			if (isOwnerAsString.equals("1")) {
				isOwner = true;
			}
	
			String parentFolderIdAsString = request
					.getParameter("parentFolderId");
			if (parentFolderIdAsString == null) {
				throw new ServletException("Missing parentFolderId ID");
			}
			Long parentFolderId = Long.parseLong(parentFolderIdAsString);
	
			MultipartFile multipartFile = info.file;
			InputStream is = multipartFile.getInputStream();
			log.debug("fileSystemName: " + info.filename);
	
			ConverterProcessResultList returnError = fileProcessor
					.processFile(info.userId, room_id_to_Store, isOwner, is,
							parentFolderId, info.filename, 0L, ""); // externalFilesId, externalType
	
			UploadCompleteMessage uploadCompleteMessage = new UploadCompleteMessage();
	    	uploadCompleteMessage.setUserId(info.userId);
	
			// Flash cannot read the response of an upload
			// httpServletResponse.getWriter().print(returnError);
	    	uploadCompleteMessage.setMessage("library");
	    	uploadCompleteMessage.setAction("newFile");
	    	
	    	setFileExplorerItem(uploadCompleteMessage,
					fileExplorerItemDao.getFileExplorerItemsById(
							returnError.getFileExplorerItemId()));
			
			uploadCompleteMessage.setHasError(returnError.hasError());
			//we only send the complete log to the client if there is really something 
			//to show because of an error
			if (returnError.hasError()) {
				uploadCompleteMessage.setError(returnError.getLogMessage());
			}
			uploadCompleteMessage.setFileName(returnError.getCompleteName());
			
			sendMessage(info, uploadCompleteMessage);
		} catch (ServletException e) {
			throw e;
		} catch (Exception e) {
			log.error("Exception during upload: ", e);
			throw new ServletException(e);
    	}
    }
    
	public void setFileExplorerItem(UploadCompleteMessage msg, FileExplorerItem fileExplorerItem) {
		if (fileExplorerItem.getIsImage() != null) {
			msg.setIsImage(fileExplorerItem.getIsImage());
		}
		if (fileExplorerItem.getIsVideo() != null) {
			msg.setIsVideo(fileExplorerItem.getIsVideo());
		}
		if (fileExplorerItem.getIsPresentation() != null) {
			msg.setIsPresentation(fileExplorerItem.getIsPresentation());
		}
		msg.setFileSystemName(fileExplorerItem.getFileName());
		msg.setFileHash(fileExplorerItem.getFileHash());
	}
    
    @RequestMapping(value = "/remotelog.upload", method = RequestMethod.POST)
    public void handleRemoteLog(HttpServletRequest request, HttpServletResponse response) throws ServletException {
    	String message = request.getParameter("message");
    	String sid = request.getParameter("sid");
    	if (sid == null || message == null) return;
    	Long userId = sessiondataDao.checkSession(sid);
    	if (userId != null && userId != 0) {
    		log.debug("[CLIENT MESSAGE] " + message);
    	}
    }
    
    @RequestMapping(value = "/upload.upload", method = RequestMethod.POST)
    public void handleFormUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException {
		try {
	    	UploadInfo info = validate(request, false);
	    	
			String room_id = request.getParameter("room_id");
			if (room_id == null) {
				room_id = "default";
			}
			String roomName = StringUtils.deleteWhitespace(room_id);
	
			String moduleName = request.getParameter("moduleName");
			if (moduleName == null) {
				moduleName = "nomodule";
			}
			if (moduleName.equals("nomodule")) {
				log.debug("module name missed");
				return;
			}
			boolean userProfile = moduleName.equals("userprofile");
	
			MultipartFile multipartFile = info.file;
			InputStream is = multipartFile.getInputStream();
			String fileSystemName = info.filename;
			fileSystemName = StringUtils.deleteWhitespace(fileSystemName);
	
			UploadCompleteMessage uploadCompleteMessage = new UploadCompleteMessage();
	    	uploadCompleteMessage.setUserId(info.userId);
			
			// Flash cannot read the response of an upload
			// httpServletResponse.getWriter().print(returnError);
			uploadFile(request, userProfile, info.userId, roomName, is, fileSystemName, uploadCompleteMessage);
			sendMessage(info, uploadCompleteMessage);
		} catch (ServletException e) {
			throw e;
		} catch (Exception e) {
			log.error("Exception during upload: ", e);
			throw new ServletException(e);
		}
    }

    
    private void sendMessage(UploadInfo info, UploadCompleteMessage uploadCompleteMessage) {
		scopeApplicationAdapter.sendUploadCompletMessageByPublicSID(
				uploadCompleteMessage, info.publicSID);
    }
    
	private void uploadFile(HttpServletRequest request, boolean userProfile, Long userId, String roomName,
			InputStream is, String fileSystemName, UploadCompleteMessage uploadCompleteMessage)
			throws Exception {
		ConverterProcessResultList returnError = new ConverterProcessResultList();

		// Check variable to see if this file is a presentation
		int dotidx = fileSystemName.lastIndexOf('.');
		String newFileName = StringComparer.getInstance().compareForRealPaths(
				fileSystemName.substring(0, dotidx));
		String newFileExtDot = fileSystemName.substring(dotidx,
				fileSystemName.length()).toLowerCase();
		String newFileExt = newFileExtDot.substring(1);

		// trim long names cause cannot output that
		final int MAX_FILE_NAME_LENGTH = 30;
		if (newFileName.length() >= MAX_FILE_NAME_LENGTH) {
			newFileName = newFileName.substring(0, MAX_FILE_NAME_LENGTH);
		}
		StoredFile storedFile = new StoredFile(newFileName, newFileExt);

		// check if this is a a file that can be converted by
		// openoffice-service
		boolean canBeConverted = storedFile.isConvertable();
		boolean isPdf = storedFile.isPdf();
		boolean isImage = storedFile.isImage();
		boolean isAsIs = storedFile.isAsIs();

		File workingDir = null;
		// add outputfolders for profiles
		if (userProfile) {
			// User Profile Update
			this.deleteUserProfileFilesStoreTemp(userId);
			newFileName = "profile"; //set unified file name to avoid any problems with national characters
			workingDir = OmFileHelper.getUploadProfilesUserDir(userId);
		}
		// if it is a presenation it will be copied to another
		// place
		if (isAsIs) {
			// check if this is a room file or UserProfile
			if (!userProfile) {
				workingDir = OmFileHelper.getUploadRoomDir(roomName);
			}
		} else if (canBeConverted || isPdf || isImage) {
			workingDir = OmFileHelper.getUploadTempProfilesUserDir(userId);
		} else {
			return;
		}

		File completeName = OmFileHelper.getNewFile(workingDir, newFileName, newFileExtDot);

		log.debug("write file to : " + completeName);

		FileHelper.copy(is, completeName);
		is.close();

		log.debug("canBeConverted: " + canBeConverted);
		if (canBeConverted) {
			// convert to pdf, thumbs, swf and xml-description
			returnError = generatePDF.convertPDF(newFileName, roomName, true, completeName);
		} else if (isPdf) {
			
			boolean isEncrypted = true; 
			
			log.debug("isEncrypted :: " + isEncrypted);

			if (isEncrypted) {
				// Do convert pdf to other pdf first
				File f_old = completeName;

				completeName = OmFileHelper.appendSuffix(completeName, "_N_E");
				newFileName += "_N_E";

				generateThumbs.decodePDF(f_old.getCanonicalPath(), completeName.getCanonicalPath());

				if (f_old.exists()) {
					f_old.delete();
				}

			}

			// convert to thumbs, swf and xml-description
			returnError = generatePDF.convertPDF(newFileName, roomName, false, completeName);

			// returnError.put("decodePDF", returnError2);

		} else if (isImage && !isAsIs) {

			log.debug("##### isImage! userProfilePic: " + userProfile);

			if (userProfile) {
				// convert it to JPG
				returnError = generateImage.convertImageUserProfile(completeName, userId, true);
			} else {
				// convert it to JPG
				log.debug("##### convert it to JPG: " + userProfile);
				returnError = generateImage.convertImage(
					newFileName, newFileExtDot, roomName, newFileName, false);
			}
		} else if (isAsIs) {
			if (userProfile) {
				// User Profile Update
				this.deleteUserProfileFiles(userId);
				// is UserProfile Picture
				returnError.addItem("processThumb1", generateThumbs
						.generateThumb(chatImagePrefix, completeName, 40));
				returnError.addItem("processThumb2", generateThumbs
						.generateThumb(profileImagePrefix, completeName, 126));
				returnError.addItem("processThumb3", generateThumbs
						.generateThumb(bigImagePrefix, completeName, 240));

				String pictureuri = completeName.getName();
				User us = usersDao.get(userId);
				us.setUpdatetime(new java.util.Date());
				us.setPictureuri(pictureuri);
				usersDao.update(us, userId);

				//FIXME: After updating the picture url all other users should refresh
			} else {
				returnError.addItem("processThumb", generateThumbs
						.generateThumb(thumbImagePrefix, completeName, 50));
			}
		}

		uploadCompleteMessage.setMessage("library");
		uploadCompleteMessage.setAction("newFile");
		
		uploadCompleteMessage.setHasError(returnError.hasError());
		
		//we only send the complete log to the client if there is really something 
		//to show because of an error
		if (returnError.hasError()) {
			uploadCompleteMessage.setError(returnError.getLogMessage());
		}
		uploadCompleteMessage.setFileName(completeName.getName());
		
	}

	private void deleteUserProfileFilesStoreTemp(Long users_id) throws Exception {
		File f = OmFileHelper.getUploadProfilesUserDir(users_id);
		if (f.exists() && f.isDirectory()) {
			this.filesString = f.list();
		}
	}

	private void deleteUserProfileFiles(Long users_id) throws Exception {
		File working_imgdir = OmFileHelper.getUploadProfilesUserDir(users_id);

		for (int i = 0; i < this.filesString.length; i++) {
			String fileName = filesString[i];
			File subf = new File(working_imgdir, fileName);
			subf.delete();
		}
	}
}
