package jp.hasc.loggerserver;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.List;

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

import jp.hasc.hasctool.core.util.CoreUtil;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;

public class HascUploaderServlet extends HttpServlet
{
	/** logger for this class */
	private final static org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
			.getLog(HascUploaderServlet.class);
	
	private static final String TEMP_NAME = "hasc_tool_temp";

	private static final long serialVersionUID = 1L;

	//public static IFolder basefolder = null;
	private File tempDir_;

	public HascUploaderServlet(){
	}
	
	@Override
	public void init() throws ServletException {
		// temp dir
		tempDir_=new File(System.getProperty("java.io.tmpdir"),TEMP_NAME);
		tempDir_.mkdirs();
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		response.setContentType("text/plain");
		response.getWriter().print("It works.");
		response.setStatus(HttpServletResponse.SC_OK);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse response)
	throws ServletException, IOException {
		if (!ServletFileUpload.isMultipartContent(req)) {
			response.setContentType("text/plain");
			response.getWriter().print("Not multipart content");
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return;
		}
		
		/*{
			// for debug
			byte[] buff=new byte[65536];
			ServletInputStream inps = req.getInputStream();
			inps.read(buff,0,buff.length);
			String s=new String(buff);
			System.out.println(s);
		}*/
		
		try {
			// Create a factory for disk-based file items
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//factory.setSizeThreshold(0);
			factory.setRepository(tempDir_);
	
			// Create a new file upload handler
			ServletFileUpload upload = new ServletFileUpload(factory);
	
			// Parse the request
			@SuppressWarnings("unchecked")
			List<FileItem> items = upload.parseRequest(req);
			for(FileItem item : items) {
			    String fieldName = item.getFieldName();
				if (item.isFormField()) {
					// do nothing
				}else{
				    if (fieldName.equals("logfile")) {
				    	processLogFile(item);
				    }else if (fieldName.equals("audiofile")) {
				    	processAudioFile(item);
				    }
				}
			}
			
			//
			response.setContentType("text/plain");
			response.getWriter().print("done");
			response.setStatus(HttpServletResponse.SC_OK);
			
		} catch (Exception ex) {
			ex.printStackTrace();
			response.setContentType("text/plain");
			response.getWriter().print(ex.toString());
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return;
		}
	}
	
	private String getNewFileName(String fileName, String basename_postfix, String ext) {
		int pidx=Math.max(fileName.lastIndexOf("/"),fileName.lastIndexOf("\\"));
		if (pidx>=0) fileName=fileName.substring(pidx+1);
		//
		int idx=fileName.lastIndexOf('.');
		if (ext==null) {
			if (idx>=0) ext=fileName.substring(idx); else ext="";
		}
		if (idx>=0) {
			fileName=fileName.substring(0,idx)+basename_postfix+ext;
		}else{
			fileName=fileName+basename_postfix+ext;
		}
		return fileName;
	}
	
	private File getTempFile(String fileName,String postfix) {
		return new File(tempDir_,getNewFileName(fileName,"","")+"-"+postfix);
	}
	
	private void processAudioFile(FileItem item) throws Exception {
		String fileName=item.getName();
		File f=getTempFile(fileName,"audio");
		item.write(f);
		String newFileName = getNewFileName(fileName,"-audio",null);
		IFile outf=saveToResourceFileAndClose(new FileInputStream(f), newFileName);
		item.delete();
		f.delete();
		try{
			CoreUtil.convertAudioFile(outf);
		}catch(Exception ex) {
			LOG.warn("Audio conversion failed: "+ex.toString());
		}
	}

	private void processLogFile(FileItem item) throws Exception {
		String fileName=item.getName();
		File f=getTempFile(fileName,"logfile");
		item.write(f);
		saveToResourceFileAndClose(new FileInputStream(f), getNewFileName(fileName,"-raw",".log"));
		saveAccFile(fileName,new FileInputStream(f));
		item.delete();
		f.delete();
	}

	private void saveAccFile(String fileName, InputStream inps) throws IOException, CoreException, InterruptedException{
		BufferedReader br=new BufferedReader(new InputStreamReader(inps));
		//
		File metaTempFile = getTempFile(fileName,"meta");
		Writer metaWriter = new FileWriter(metaTempFile);
		boolean acc = false;
		File accTempFile = getTempFile(fileName,"acc");
		Writer accWriter = new FileWriter(accTempFile);
		boolean gyro = false;
		File gyroTempFile = getTempFile(fileName,"gyro");
		Writer gyroWriter = new FileWriter(gyroTempFile);
		boolean mag = false;
		File magTempFile = getTempFile(fileName,"mag");
		Writer magWriter = new FileWriter(magTempFile);
		boolean heading = false;
		File headingTempFile = getTempFile(fileName,"heading");
		Writer headingWriter = new FileWriter(headingTempFile);
		boolean loc = false;
		File locTempFile = getTempFile(fileName,"loc");
		Writer locWriter = new FileWriter(locTempFile);
		boolean pressure = false;
		File pressureTempFile = getTempFile(fileName,"pressure");
		Writer pressureWriter = new FileWriter(pressureTempFile);
		boolean light = false;
		File lightTempFile = getTempFile(fileName,"light");
		Writer lightWriter = new FileWriter(lightTempFile);
		boolean proximity = false;
		File proximityTempFile = getTempFile(fileName,"proximity");
		Writer proximityWriter = new FileWriter(proximityTempFile);
		//
		try {
			while(true) {
				String line = br.readLine();
				if (line==null) break;
				//System.out.println("["+line+"]");
				if(line.contains("ACC")){
					String dd[] = line.split("ACC\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						accWriter.write(dd[1]+"\n");
						if(!acc)acc = true;
					}
				}else if(line.contains("GYRO")){
					String dd[] = line.split("GYRO\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						gyroWriter.write(dd[1]+"\n");
						if(!gyro)gyro = true;
					}
				}else if(line.contains("MAG")){
					String dd[] = line.split("MAG\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						String[] row = dd[1].split(",");
						if (row.length>3) {
							magWriter.write(row[0]+","+row[1]+","+row[2]+","+row[3]+"\n");
						}else{
							magWriter.write(dd[1]+"\n");
						}
						if(!mag)mag = true;
					}
				}else if(line.contains("HEADING")){
					String dd[] = line.split("HEADING\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						String[] row = dd[1].split(",");
						//System.out.println(dd[1]);
						//System.out.println(row[0]+","+row[1]+","+row[2]+","+row[3]);
						if (row.length>3) {
							headingWriter.write(row[0]+","+row[1]+","+row[2]+","+row[3]+"\n");
							if(!heading)heading = true;
						}
					}
				}else if(line.contains("LOC")){
					String dd[] = line.split("LOC\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						locWriter.write(dd[1]+"\n");
						if(!loc)loc = true;
					}
				}else if(line.contains("PRESSURE")){
					String dd[] = line.split("PRESSURE\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						pressureWriter.write(dd[1]+"\n");
						if(!pressure)pressure = true;
					}
				}else if(line.contains("LIGHT")){
					String dd[] = line.split("LIGHT\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						lightWriter.write(dd[1]+"\n");
						if(!light)light = true;
					}
				}else if(line.contains("PROXIMITY")){
					String dd[] = line.split("PROXIMITY\t");
					//System.out.println("("+dd[1]+")");
					if(dd.length >1){
						proximityWriter.write(dd[1]+"\n");
						if(!proximity)proximity = true;
					}
				}else if(line.contains("TAGS")){
					String dd[] = line.split("TAGS\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("Tags: "+dd[1]+"\n");					
				}else if(line.contains("LOG_VERSION")){
					String dd[] = line.split("LOG_VERSION\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("LogVersion: "+dd[1]+"\n");					
				}else if(line.contains("TERMINAL_ID")){
					String dd[] = line.split("TERMINAL_ID\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("TerminalID: "+dd[1]+"\n");					
				}else if(line.contains("TERMINAL_TYPE")){
					String dd[] = line.split("TERMINAL_TYPE\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("TerminalType: "+dd[1]+"\n");					
				}else if(line.contains("COMMENT")){
					String dd[] = line.split("COMMENT\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("Comment: "+dd[1]+"\n");					
				}else if(line.contains("CLIENT_VERSION")){
					String dd[] = line.split("CLIENT_VERSION\t");
					//					System.out.println("("+dd[1]+")");
					if(dd.length >1)
						metaWriter.write("ClientVersion: "+dd[1]+"\n");					
				}else{
					System.out.println("no output["+line+"]");
				}
			}

		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			br.close();
			metaWriter.close();
			accWriter.close();
			gyroWriter.close();
			magWriter.close();
			headingWriter.close();
			locWriter.close();
			pressureWriter.close();
			lightWriter.close();
			proximityWriter.close();
		}
		
		// output for IDirectory
		if(acc) saveToResourceFileAndClose(new FileInputStream(accTempFile),getNewFileName(fileName,"-acc",".csv"));
		accTempFile.delete();
		if(gyro) saveToResourceFileAndClose(new FileInputStream(gyroTempFile),getNewFileName(fileName,"-gyro",".csv"));
		gyroTempFile.delete();
		if(mag) saveToResourceFileAndClose(new FileInputStream(magTempFile),getNewFileName(fileName,"-mag",".csv"));
		magTempFile.delete();
		if(heading) saveToResourceFileAndClose(new FileInputStream(headingTempFile),getNewFileName(fileName,"-heading",".csv"));
		headingTempFile.delete();
		if(loc) saveToResourceFileAndClose(new FileInputStream(locTempFile),getNewFileName(fileName,"-loc",".csv"));
		locTempFile.delete();
		if(pressure) saveToResourceFileAndClose(new FileInputStream(pressureTempFile),getNewFileName(fileName,"-pressure",".csv"));
		pressureTempFile.delete();
		if(light) saveToResourceFileAndClose(new FileInputStream(lightTempFile),getNewFileName(fileName,"-light",".csv"));
		lightTempFile.delete();
		if(proximity) saveToResourceFileAndClose(new FileInputStream(proximityTempFile),getNewFileName(fileName,"-proximity",".csv"));
		proximityTempFile.delete();
		saveToResourceFileAndClose(new FileInputStream(metaTempFile),getNewFileName(fileName,"",".meta"));
		metaTempFile.delete();
	}

	private IFile saveToResourceFileAndClose(InputStream inps,String fileName) throws CoreException, IOException, InterruptedException{
		IFile outf = HascLoggerServer.getOutputBaseFolder().getFile(fileName);
		ProgressMonitorForBlocking blk = new ProgressMonitorForBlocking();
		if (outf.exists()) {
			outf.setContents(inps, true, false, blk);
		}else{
			outf.create(inps, true, blk);
		}
		blk.awaitDone();
		inps.close();
		LOG.debug("wrote file:"+fileName);
		return outf;
	}

}