package org.gcube.execution.ocrservice.tests;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import org.apache.axis.message.addressing.AttributedURI;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
import org.gcube.common.core.scope.GCUBEScope;
import org.gcube.common.core.types.VOID;
import org.gcube.execution.ocrservice.stubs.*;
import org.gcube.execution.ocrservice.stubs.service.OCRServiceAddressingLocator;
import org.gcube.execution.ocrservice.stubs.service.OCRServiceFactoryServiceAddressingLocator;
import org.gcube.execution.ocrservice.stubs.InputResource;
import org.gcube.execution.workflowengine.service.stubs.AccessInfo;
import org.oasis.wsrf.lifetime.Destroy;



public class TestOCRService {

	private enum	SubmissionType 	{ jdlAdaptor, gridAdaptor };
	private static 	boolean 		destroyWSResources 		= false;						// whether you want the WS resource of the job to be destroyed in the end
	private static  long			pollPeriodMilliSeconds	= 10000;						// milliseconds between polling status of indexer job
	private static  SubmissionType	subType					= SubmissionType.jdlAdaptor;	// type of submission, jdl or grid
	private static  String 			proxyPath				= "/tmp/proxy";					// location of proxy in filesystem
	private static  boolean 		isBulk					= false;						// send bulk pdfs (.zip) or single pdf
	private static  String			owner					= "TestOCRService_Client";
	private static  boolean			chokePDFOutput			= false;					//if you don't need pdf to be stored
	private static  boolean  		storeFTP				= false;					//if you want output to be stored int ftp

	//ftp credentials ftp://:
	private static  String ftpUsername =  		"­renats";
	private static  String ftpPassword = 		"123456";
	private static  String ftpPort 	   = 		"-1";
	private static  String ftpLocation = 	"ftp://mpagasas.di.uoa.gr/b4ba3a10-b47d-11e0-9e5d-fda94ff03826";
	
	
	
	public static void main(String[] args)  {

		final String usage = "Usage: 	java org.gcube.execution.ocrservice.tests.TestOCRService <ocr factory address> <gcube scope> <resource key> <resource access> <value> <language> <optional job name in >=0 words >\n" + 
				"\n" + 
				"Example 1:\n" + 
				"	java org.gcube.execution.ocrservice.tests.TestOCRService http://jazzman.di.uoa.gr:8080/wsrf/services/gcube/execution/ocrservice/OCRServiceFactory /d4science.research-infrastructures.eu/INSPIRE NobelAnnounce.pdf Reference http://dl.dropbox.com/u/19792897/NobelAnnounce.pdf eng OCR on NobelAnnouce 2 page document \n" + 
				"\n" + 
				"Example 2:\n" + 
				"	java org.gcube.execution.ocrservice.tests.TestOCRService http://jazzman.di.uoa.gr:8080/wsrf/services/gcube/execution/ocrservice/OCRServiceFactory /d4science.research-infrastructures.eu/INSPIRE NobelAnnounce.pdf CMSReference cms://ab2f4d80-87b1-11e0-9fbc-f078a392f5cc/b1beaf60-87b1-11e0-9fbc-f078a392f5cc eng OCR on NobelAnnouce 2 page document \n" + 
				"\n" + 
				"Example 3a:\n" + 
				"	java org.gcube.execution.ocrservice.tests.TestOCRService http://jazzman.di.uoa.gr:8080/wsrf/services/gcube/execution/ocrservice/OCRServiceFactory /d4science.research-infrastructures.eu/INSPIRE NobelAnnounce.pdf InMessageString /home/stefanos/NobelAnnounce.pdf eng OCR on NobelAnnouce 2 page document \n" + 
				"\n" + 
				"Example 3b:\n" + 
				"	java org.gcube.execution.ocrservice.tests.TestOCRService http://jazzman.di.uoa.gr:8080/wsrf/services/gcube/execution/ocrservice/OCRServiceFactory /d4science.research-infrastructures.eu/INSPIRE NobelAnnounce.pdf InMessageBytes /home/stefanos/NobelAnnounce.pdf eng OCR on NobelAnnouce 2 page document \n" + 
				"";
		
		try {

			//Client needs 6+ arguments
			if(args.length<6){
				System.err.println(usage);
				System.exit(1);
			}
			
			String jobName="";
			for(int i=6; i<args.length; i++)
				jobName+= args[i] + " ";
			
			System.out.println("");
			System.out.println("TestOCRService client started with arguments:");
			System.out.println("OCR Factory Service: "+ args[0] );
			System.out.println("Scope:               "+ args[1] );
			System.out.println("Key:                 "+ args[2] );
			System.out.println("Access:              "+ args[3] );
			System.out.println("Value:               "+ args[4] );
			System.out.println("Language:            "+ args[5] );
			System.out.println("JobName:             "+ jobName );
			System.out.println("isBulk:              "+ isBulk  );
			System.out.println("Adaptor:             "+ subType.toString());
			System.out.println("Choke pdf output:    "+ chokePDFOutput);
			System.out.println("Store in ftp:        "+ storeFTP);

		
			EndpointReferenceType factoryEPR = new EndpointReferenceType(new AttributedURI(args[0]));
			System.out.println("\nGetting factory stub...");
			OCRServiceFactoryPortType stub1 = new OCRServiceFactoryServiceAddressingLocator().getOCRServiceFactoryPortTypePort(factoryEPR);
			stub1 = GCUBERemotePortTypeContext.getProxy(stub1,GCUBEScope.getScope(args[1].trim()));

			System.out.println("Preparing input of OCR job...");
			Submit sub=new Submit();

			//set language of input
			sub.setLanguage(getLanguageFromString(args[5]));
		
			//set ftp credentials
			AccessInfoFTP 	ftpAccess = new AccessInfoFTP();
		//	ftpAccess.setGarbage("ignore this");
			ftpAccess.setUserName("renats");
			
			ftpAccess.setPassword(ftpPassword.trim());
			ftpAccess.setLocation(ftpLocation.trim());
			
				ftpAccess.setPort(ftpPort);
			sub.setFtpAccess(ftpAccess);
			
			//set input
			InputResource input=new InputResource();

			//Case 1: give input as FTP reference
			if(args[3].equals("Reference")){
				input.setResourceKey(args[2]);
				input.setResourceAccess("Reference");
				input.setResourceReference(args[4]);
			}
			//Case 2: give input as CMS reference
			else if(args[3].equals("CMSReference")){
				input.setResourceKey(args[2]);
				input.setResourceAccess("CMSReference");
				input.setResourceReference(args[4]);
			}
			//Case 3a: send input's payload in string form
			else if(args[3].equals("InMessageString")){
				input.setResourceKey(args[2]);
				input.setResourceAccess("InMessageString");
				input.setInMessageStringPayload( TestOCRService.GetStringFilePayload(args[4]));
			}
			//Case 3b: send input's payload in byte form
			else if(args[3].equals("InMessageBytes")){
				input.setResourceKey(args[2]);
				input.setResourceAccess("InMessageBytes");
				input.setInMessageBytePayload( TestOCRService.GetByteFilePayload(args[4]));
			}
			else{
				System.err.println(usage);
				System.exit(1);
			}
			
			//in case of grid adaptor, give proxy
			if( TestOCRService.subType ==  SubmissionType.gridAdaptor ){
				try{
					sub.setGridProxy( GetByteFilePayload(TestOCRService.proxyPath ));
				}catch(Exception ex){
					throw new Exception("To submit ocr job with grid adaptor, put proxy in " + proxyPath);
				}
			}
			
			///---> Submit OCR job
			sub.setOwner(owner);
			sub.setJobName(jobName);
			sub.setInputResource(input);
			sub.setChokePDFOutput(chokePDFOutput);
			sub.setStoreFTP(storeFTP);
			
			System.out.println("Submitting OCR job...");
			
			//single pdf submission
			EndpointReferenceType resourceEpr = null;
			if( isBulk==false){
				resourceEpr = stub1.submit(sub).getEndpointReference();
			}
			else{
				resourceEpr = stub1.submitBulk(TestOCRService.replaceStubsToBulk(sub)).getEndpointReference();
			}

			OCRServicePortType stub2 = new  OCRServiceAddressingLocator().getOCRServicePortTypePort(resourceEpr);
			stub2=GCUBERemotePortTypeContext.getProxy(stub2,GCUBEScope.getScope(args[1]));
			System.out.println("OCR job was submitted");
			
			//---> poll status every TestOCRService.pollPeriodMilliSeconds seconds until completion
			System.out.println("Calling status() until completion\n");
			StatusResponseType status=null;
			do{
				
				status= stub2.status( new VOID() );
				System.out.println("Description:    " + status.getStatusDescription());
				System.out.println("Last poll date: " + status.getLastPollDate() );
				System.out.println("");
				Thread.sleep(TestOCRService.pollPeriodMilliSeconds);

			}while (status.isCompleted()==false);

			//delete WS-resource
			if(TestOCRService.destroyWSResources==true)
				stub2.destroy( new Destroy() );
			
			System.out.println("");
			System.out.println("OCR Job has finished:");
			System.out.println("-----------------------------------------------------");
			System.out.println("Job Name:        " +     status.getJobName());
			System.out.println("Description:     " +     status.getStatusDescription());
			System.out.println("Submited:        " +	 status.getSubmitDate());
			System.out.println("Last Poll:       " +	 status.getLastPollDate());
			System.out.println("Error:           " +	 status.getError());
			System.out.println("ErrorDetails:    " + 	 status.getErrorDetails());
			System.out.println("hocr   ssid: 	 " + 	 status.getHocrOutputSSID());
			System.out.println("pdf    ssid: 	 " + 	 status.getPdfOutputSSID());
			System.out.println("stdout ssid: 	 " + 	 status.getJoboutSSID());
			System.out.println("stderr ssid: 	 " + 	 status.getJoberrSSID());
						
		}catch(Exception ex){
			ex.printStackTrace();
		}

	}
	
	
	
	public static String GetStringFilePayload(String path) throws IOException
	{
		BufferedReader reader=new BufferedReader(new FileReader(new File(path)));
		StringBuilder buf=new StringBuilder();
		while(true)
		{
			String line = reader.readLine();
			if(line==null) break;
			buf.append(line);
			buf.append("\n");
		}
		reader.close();
		return buf.toString();
	}

	public static byte[] GetByteFilePayload(String path) throws IOException
	{
		ByteArrayOutputStream bout=new ByteArrayOutputStream();
		BufferedInputStream bin=new BufferedInputStream(new FileInputStream(new File(path)));
		byte []b=new byte[4*1024];
		while(true)
		{
			int read=bin.read(b);
			if(read<0) break;
			bout.write(b, 0, read);
		}
		bin.close();
		bout.flush();
		bout.close();
		return bout.toByteArray();
	}
	
		
	private static LanguageEnumType 	getLanguageFromString(String language) throws Exception{
		
		if(language==null)
			return LanguageEnumType.eng;
		else if(language.trim().equals("eng"))
			return LanguageEnumType.eng;
		else if(language.trim().equals("deu"))
			return LanguageEnumType.deu;
		else if(language.trim().equals("fra"))
			return LanguageEnumType.fra;
		else if(language.trim().equals("ita"))
			return LanguageEnumType.ita;
		else if(language.trim().equals("nld"))
			return LanguageEnumType.nld;
		else if(language.trim().equals("spa"))
			return LanguageEnumType.spa;
		else throw new Exception("Invalid language '"+ language +"' (valid values are: eng,deu,fra,ita,nld,spa)");
		
	}
	
	
	private static SubmitBulk 		replaceStubsToBulk(Submit sub){
		SubmitBulk sub2 = new SubmitBulk();
		sub2.setGridProxy(sub.getGridProxy());
		sub2.setInputResource(sub.getInputResource());
		sub2.setJobName(sub.getJobName());
		sub2.setLanguage(sub.getLanguage());
		sub2.setOwner(sub.getOwner());
		return sub2;
	}
	
	
	
}
