import com.dvelop.d3.server.Document
import com.dvelop.d3.server.DocumentType
import com.dvelop.d3.server.core.D3Interface
import com.dvelop.d3.server.User
import groovy.sql.*
import groovy.transform.Field
import org.apache.commons.io.FileUtils;
import java.text.SimpleDateFormat

/*
 * Beschreibung: Liesst die Dokumente an 
 * 
 */
	//Pfade zur Auslesen und Ablegen der Vertragsdateien inkl. JPL
	@Field String path = "E:\\WORK_LCM_MIGR\\export\\part0"
	@Field String TargetPath = "E:\\WORK_LCM_MIGR\\export\\Import_Folder\\"
	//@Field String TargetPath = "E:\\d3work\\Import\\D3D\\Vertragsdok_Unt\\"
	
	/* Modus der Dokument Migration
	*  All_Dok - Migriert alle in Ordner @path liegenden Dokumente. Dokumente ohne bestehenden Vertrag, 
	*  bekommen keine Vertragsnummer intern und sind somit nicht verknuepft
	*  Only_Available - Migriert nur die vertragsdokumente die zu den Vertraegen der LCM Nummern des Filters @SQLQueryFilter gehoeren.
	*/
	@Field String modus = "All_Dok"//"Only_Available"
	//Filter zur Eingrenzung der Dokumente. Diese Variable wird nur im Modus @modus - Only_Available verwendet.
	@Field String SQLQueryFilter = " WHERE O.FK_TBL_VERTRAG IN ('13220','14141','14170','14174','14176','14177','14178','14179','14180','16256','16395','16397','16399','16400','16401','16402','16403','16404','16406','16407','16446','16450','16451','16452','16453','16454','16455','17358','21240','21295','21573','13705','16712','15120','16052','12301','18970')"
	//Beinhaltet die Vertragsnummer von Vertraegen die mehrere Vertragsdokumente im LCM besitzen. Diese Dokumente werden dann Vertragsunterlagen mit dem Typ Vertrag
	@Field List<String> contractMap
	
	public class constanten
	{
		// Logging
		static String logDirPath = "./log/"
		static File logFile = new File(logDirPath + System.currentTimeMillis() + "DokumentenImportDCM.log")
	}
	
	D3Interface d3 = getProperty("d3")
	d3.log.info("Start Dokumente in Vertrag ablegen");
	getContractWithMoreContractDocs(d3)
	getDocuments(d3)
	d3.log.info("Ende Dokumente in Vertrag ablegen");

	def getDocuments (D3Interface d3) 
	{	
		if(modus == "All_Dok")
		{
			d3.log.info("Start getDocuments - All_Dok Modus");
			File folder = new File(path);
			findAllFilesInFolder(d3,folder)
			copyFiles(d3)
			d3.log.info("Ende getDocuments - All_Dok Modus");
		}
		else if(modus == "Only_Available")
		{
			d3.log.info("Start getDocuments - Only_Available Modus");
			getOnlyDocumentsForDefinedContracts(d3)
			d3.log.info("Ende getDocuments - Only_Available Modus");
		}
		else
		{
			throw new Exception ("Fehler: Es wurde ein falscher Modus verwendet. Bitte nur 'Only_Available' oder 'All_Dok' verwenden.");
		}
	}
	
	def copyFiles(D3Interface d3)
	{
		File source = new File(path);
		File dest = new File(TargetPath);
		try {
			FileUtils.copyDirectory(source, dest);
		} 
		catch (IOException e) 
		{
			d3.log.error("Fehler: " + e)
		}
	}
	
	def findAllFilesInFolder(D3Interface d3, File folder) 
	{
		d3.log.info("Start findAllFilesInFolder");
		for (File file : folder.listFiles()) {
			d3.log.info("Dokument ist in Ordner vorhanden");
			if (!file.isDirectory()) {
				d3.log.info("FileName: " + file.getName());
				// Auslesen der Dokument ID
				String fileName = file.getName();
				//Number--------
				int ende = fileName.indexOf(".");
				int start = fileName.indexOf("_")+1;
				String substring = fileName.substring(start , ende);
				d3.log.info("substring: " + substring);
				getFolderNumber(d3, substring, fileName)
			} else {
				findAllFilesInFolder(d3, file);
			}
		}
		d3.log.info("Ende findAllFilesInFolder");
	}
		
	def getFolderNumber(D3Interface d3, String document_Number, String OriginalFileName)
	{
		d3.log.info("Start getContract");
		
		def lDBUser = "US_DEVELOP_RO"
		def lDBPasssword = "US_DEVELOP_RO"
		def lSQLConnection
		try
		{
			String SQLQuery = "Select db.fk_tbl_dokument_id, db.filename, o.titel, O.FK_TBL_VERTRAG, O.FK_REF_DOKUMENTENTYP, da.FK_REF_ATTDL1 , da.FK_REF_ATTDL2, da.FK_REF_ATTDL4, da.FK_REF_ATTDL5, o.FK_REF_DOKUMENT_STATUS, vd.FK_TBL_ORDNER, ORD.BEZEICHNUNG FROM DMS.tbl_dokument_binary db FULL OUTER JOIN DMS.tbl_dokument O ON O.id = db.FK_TBL_DOKUMENT_ID FULL OUTER JOIN LCMDESIGNER.tbl_dokument_attribute da ON da.fk_tbl_dokument = O.id FULL OUTER JOIN LCM.TBL_VERTRAG_DOKUMENT VD ON VD.fk_tbl_dokument = O.id FULL OUTER JOIN DMS.TBL_ORDNER ORD ON ORD.ID = vd.FK_TBL_ORDNER WHERE db.fk_tbl_dokument_id = $document_Number"
			lSQLConnection = Sql.newInstance( "jdbc:oracle:thin:@//olxdedevoradb01.dev.otc.hlg.de:1521/SD011A", lDBUser, lDBPasssword, "oracle.jdbc.driver.OracleDriver" );
			lSQLConnection.eachRow(SQLQuery) { row ->
				d3.log.info("id: ${row.fk_tbl_dokument_id}, Dok Name: ${row.filename}, Vertrag: ${row.FK_TBL_VERTRAG}")
				def LCM_Number = "LCM-${row.FK_TBL_VERTRAG}"
				d3.log.info("LCM_Number: " + LCM_Number)
				def VertInt = getVertragsnummer_Intern(d3, LCM_Number)
				d3.log.info("Vertragsnummer Intern: " + VertInt)
				def dokType = row.FK_REF_DOKUMENTENTYP
				d3.log.info("dokType: " + dokType)
				def dok_Status = row.FK_REF_DOKUMENT_STATUS

				createJPLFileForFile(d3, VertInt, OriginalFileName, path, dokType, dok_Status, row) 
				createActionFileForFile(d3, OriginalFileName, path) 
			}
		}
		catch(Exception e)
		{
			d3.log.error("Fehler beim SQL Verbindungsaufbau:" + e);
		}
		finally
		{	
			if(lSQLConnection != null)
			{
				lSQLConnection.close();
			}
		}
		d3.log.info("Ende getContract");
	}
	
	def getVertragsnummer_Intern(D3Interface d3, def LCM_Number)
	{
		d3.log.info("Start getVertragsnummer_Intern $LCM_Number")
		
		String query = "SELECT dok_dat_feld_11 AS VertragsIntern FROM firmen_spezifisch WHERE kue_dokuart = ? AND dok_dat_feld_12 = ?";
		GroovyRowResult resultRow = d3.sql.firstRow(query, ["A1LE3", LCM_Number]);
		if(resultRow != null && resultRow.containsKey("VertragsIntern" ) && resultRow.getProperty("VertragsIntern") != null) {
			String VertInt = resultRow.getProperty("VertragsIntern");
			d3.log.info("VertInt: " + VertInt)
			return VertInt
		}
		d3.log.info("Ende getVertragsnummer_Intern")
		return ""
	}
	
	def getOnlyDocumentsForDefinedContracts(D3Interface d3)
	{
		d3.log.info("Start getOnlyDocumentsForDefinedContracts");
		
		def lDBUser = "US_DEVELOP_RO"
		def lDBPasssword = "US_DEVELOP_RO"
		def lSQLConnection
		try
		{
			String SQLQuery = "Select db.fk_tbl_dokument_id, db.filename, o.titel, O.FK_TBL_VERTRAG, O.FK_REF_DOKUMENTENTYP, da.FK_REF_ATTDL1 , da.FK_REF_ATTDL2, da.FK_REF_ATTDL4, da.FK_REF_ATTDL5, o.FK_REF_DOKUMENT_STATUS, vd.FK_TBL_ORDNER, ORD.BEZEICHNUNG FROM DMS.tbl_dokument_binary db FULL OUTER JOIN DMS.tbl_dokument O ON O.id = db.FK_TBL_DOKUMENT_ID FULL OUTER JOIN LCMDESIGNER.tbl_dokument_attribute da ON da.fk_tbl_dokument = O.id FULL OUTER JOIN LCM.TBL_VERTRAG_DOKUMENT VD ON VD.fk_tbl_dokument = O.id FULL OUTER JOIN DMS.TBL_ORDNER ORD ON ORD.ID = vd.FK_TBL_ORDNER $SQLQueryFilter"
			lSQLConnection = Sql.newInstance( "jdbc:oracle:thin:@//olxdedevoradb01.dev.otc.hlg.de:1521/SD011A", lDBUser, lDBPasssword, "oracle.jdbc.driver.OracleDriver" );
			lSQLConnection.eachRow(SQLQuery) { row ->
				d3.log.info("Start------------------------------------------------------------")
				def LCM_Number = "LCM-${row.FK_TBL_VERTRAG}"
				d3.log.info("Vertrag LCM Nummer: " + LCM_Number)
				def VertInt = getVertragsnummer_Intern(d3, LCM_Number)
				d3.log.info("Vertragsnummer intern zur LCM Nummer: " + VertInt)
				if(VertInt != null && VertInt != "")
				{
					String documentId = row.fk_tbl_dokument_id
					def dokType = row.FK_REF_DOKUMENTENTYP
					def dok_Status = row.FK_REF_DOKUMENT_STATUS
					d3.log.info("Dokumenten Typ: " + dokType)
					File[] allDocs = findOnlyDefinedFilesInFolder(d3, new File(path), documentId );
					if(allDocs?.size() == 1)
					{
						d3.log.info("Anzahl gefundener Dokumente: " + allDocs.size() + " zu Vertrag: " + VertInt)
						try
						{
							if(contractMap.contains(VertInt))
							{
								log("Der Vertrag " + VertInt + " enthaelt mehrere Vertragsdokumente. Somit werden diese Dokumente nun zu Unterlagen")
								dokType = 1234
							}
							d3.log.info("UebergabeParameter vor Aufruf: " + dokType + " - " + dok_Status)
							def fileName = allDocs[0].getName();
							createJPLFileForFile(d3, VertInt, fileName , path, dokType, dok_Status, row) 
							createActionFileForFile(d3,  fileName, path) 
						}
						catch(Exception ex)
						{
							d3.log.error("Fehler beim generieren der Import Dateien fuer den Vertrag " + VertInt +": " + ex)
						}
					}
					else if(allDocs?.size() > 1)
					{
						d3.log.warn("Fuer den Vertrag $VertInt wurden " + allDocs?.size() + " Dokumente mit der Dokumenten ID $documentId gefunden. Es darf nur ein Dokument vorhanden sein.")
					}
					else if(allDocs?.size() == 0)
					{
						d3.log.info("Fuer den Vertrag $VertInt wurden keine Dokumente gefunden.")
					}
				}
				else
				{
					d3.log.info("Es konnte keine Vertragsnummer intern zur LCM Nummer $LCM_Number gefunden werden.")
				}
			}
			d3.log.info("Ende+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
		}
		catch(Exception e)
		{
			d3.log.error("Fehler beim SQL Verbindungsaufbau: " + e);
		}
		finally
		{	
			if(lSQLConnection != null)
			{
				lSQLConnection.close();
			}
		}
		d3.log.info("Ende getOnlyDocumentsForDefinedContracts");
	}
	
	def findOnlyDefinedFilesInFolder(D3Interface d3, File folder, String num_Prafix) 
	{
		if(folder.isDirectory())
		{
			//list all files on directory
			File[] files = folder.listFiles(new FilenameFilter() {
				
				//apply a filter
				@Override
				public boolean accept(File doc, String name) {
					boolean result;
					if(name.endsWith("jpl"))
					{
						return false;
					}
					else
					{
						def checkName = name.substring(name.indexOf("_") + "_".length(), name.indexOf("."));
						if(checkName == num_Prafix){
							result=true;
						}
						else{
							result=false;
						}
						return result;
					}
				}
			});
			return files;
		}
		return null;
	}
	
	//Erzeugt nur fuer die uebergebenen Dokumente eine action Datei
	def createActionFileForFile(D3Interface d3, String fileName, String targetPath) 
	{
		d3.log.info("START createActionFileForFile");

		PrintWriter out = null;
		d3.log.error("Dateiname fuer Action Datei: " + fileName)
		def extension = fileName
		if(fileName != "" && fileName != null)
		{
			fileName = fileName.substring(0, fileName.lastIndexOf('.'));
			extension = extension.substring(extension.lastIndexOf('.')+1, extension.length());
			if((fileName == "" || fileName == null) && (extension == "" || extension != null))
			{
				throw new Exception ("Fehler: Es konnte kein File Name oder keine Dateierweiterung extrahiert werden.");
			}
		}
		try 
		{	
			out = new PrintWriter(targetPath + "\\" + fileName + ".action");
			out.println("import_file_ext = '${extension}'");	
		}
		catch(Exception e) 
		{
			d3.log.error("ERROR: createActionFileForFile = " + e);
		}	
		finally 
		{
			if (out != null)
			{
				out.flush();
				out.close();
			}
		}
		
		
		d3.log.info("ENDE createActionFileForFile");
	}
		
	//Erzeugt nur fuer die uebergebenen Dokumente eine JPL Datei
	def createJPLFileForFile(D3Interface d3, def vertragsnummerIntern, String fileName, String targetPath, def dokType, def dok_status, def row) 
	{
		d3.log.info("START createJPLFileForFile");
		d3.log.info("Uebergabeparameter -- dokType: " + dokType + " -- dok_status: " + dok_status);
		String logiVerzeichnis = "Fr";
		PrintWriter out = null;
		d3.log.info("Dateiname: " + fileName)
		if(fileName != "" && fileName != null && fileName.contains("."))
		{
			fileName = fileName.substring(0, fileName.lastIndexOf('.'));
			if(fileName == "" || fileName == null)
			{
				throw new Exception ("Fehler: Es konnte kein JPL File Name extrahiert werden.");
			}
		}
		try 
		{
			out = new PrintWriter(targetPath + "\\" + fileName + ".jpl");
			//out.println("zeich_nr = '${doc.id()}'"); -> nur bei Versionierung
			if(dokType == 1002)
			{
				out.println("dokuart = 'D1LE5'");
				out.println("dok_dat_feld[1] = 'Vertrag'");
			}
			else
			{
				out.println("dokuart = 'D1LE6'");
				if(dokType == 1001)
				{
					out.println("dok_dat_feld[1] = 'Mustervertrag'");
				}
				else if(dokType == 1009)
				{
					out.println("dok_dat_feld[1] = 'Verpflichtung Mindestlohn'");
				}
				else if(dokType == 1003)
				{
					out.println("dok_dat_feld[1] = 'Anlage'");
				}
				else if(dokType == 1005)
				{
					out.println("dok_dat_feld[1] = 'Kündigung'");
				}
				else if(dokType == 1004)
				{
					out.println("dok_dat_feld[1] = 'Nachtrag/Änderungsvereinbarung'");
				}
				else if(dokType == 1007)
				{
					out.println("dok_dat_feld[1] = 'Geheimhaltungsvereinbarung'");
				}
				else if(dokType == 1008)
				{
					out.println("dok_dat_feld[1] = 'Sonstiges'");
				}
				else if(dokType == 1006)
				{
					out.println("dok_dat_feld[1] = 'Zusatzvereinbarung'");
				}
				else if(dokType == 1050)
				{
					out.println("dok_dat_feld[1] = 'DS Dienstleister Audit'");
				}
				else if(dokType == 1030)
				{
					out.println("dok_dat_feld[1] = 'Vertrauliches Dokument'");
				}
				else if(dokType == 1234)// Dieser Wert ist als DokType nicht vorhanden. Er wird nur zur Eindeutigkeit verwendet um aus dem Dokument eine Unterlage mit Typ Vertrag zu machen. Das ist notwendig, da es Vertraeg mit mehreren Vertragsdokumente gibt.
				{
					out.println("dok_dat_feld[1] = 'Vertrag'");
				}
				else
				{
					out.println("dok_dat_feld[1] = 'Sonstiges'");
					d3.log.info("Die Dokumentvariante konnte nicht bestimmt werden. Mapping Nummer: " + dokType)
				}
			}
			if(dok_status == null || dok_status == "" || dok_status == 1002)
			{
				out.println("dok_dat_feld[34] = 'Aktiv'");
			}
			else if(dok_status == 5)
			{
				out.println("dok_dat_feld[34] = 'Archiviert'");
			}
			else if(dok_status == 1000)
			{
				out.println("dok_dat_feld[34] = 'Beendet'");
			}
			else if(dok_status == 1001)
			{
				out.println("dok_dat_feld[34] = 'Durch einen Nachtrag ersetzt'");
			}
			else
			{
				d3.log.error("Fehler: Der Dokumentenstatus "+ dok_status +" ist nicht definiert.");
			}
			out.println("logi_verzeichnis = '${logiVerzeichnis}'");
			out.println("dok_dat_feld[11] = '${vertragsnummerIntern}'");
			def titel = row.titel;
			out.println("dok_dat_feld[26] = '${titel}'");
			def i = 1;
			if(row.FK_REF_ATTDL1 == 1000 || row.FK_REF_ATTDL1 == 1002)
			{
				out.println("dok_dat_feld_68[${i}] = 'Change of Control'");
				i++
			}
			if(row.FK_REF_ATTDL2 == 1000)
			{
				out.println("dok_dat_feld_68[${i}] = 'AV-Vereinbarungen'");
				i++
			}			
			if(row.FK_REF_ATTDL5 == 1000)
			{
				out.println("dok_dat_feld_68[${i}] = 'Standardvertragsklauseln'");
				i++
			}				
			if(row.FK_REF_ATTDL4 == 1000)
			{
				out.println("dok_dat_feld_68[${i}] = 'Code of Conduct'");
				i++
			}
			
			def ordner = row.BEZEICHNUNG
			if(ordner != null && ordner != "")
			{
				out.println("dok_dat_feld[28] = '${ordner}'");
			}
		}
		catch(Exception e) 
		{
			d3.log.error("ERROR: createJPLFileForFileArray = " + e);
		}	
		finally 
		{
			if (out != null)
			{
				out.flush();
				out.close();
			}
		}
		
		
		d3.log.info("ENDE createJPLFileForFile");
	}
	
	def getContractWithMoreContractDocs(D3Interface d3)
	{
		d3.log.info("Start getContractWithMoreContractDocs");
		
		def lDBUser = "US_DEVELOP_RO"
		def lDBPasssword = "US_DEVELOP_RO"
		def lSQLConnection
		contractMap = new LinkedList<String>();
		try
		{
			String SQLQuery = """select FK_TBL_VERTRAG from DMS.TBL_DOKUMENT where FK_REF_DOKUMENTENTYP = '1002' group by FK_TBL_VERTRAG, FK_REF_DOKUMENTENTYP Having count(*) >1""";
			lSQLConnection = Sql.newInstance( "jdbc:oracle:thin:@//olxdedevoradb01.dev.otc.hlg.de:1521/SD011A", lDBUser, lDBPasssword, "oracle.jdbc.driver.OracleDriver" );
			lSQLConnection.eachRow(SQLQuery) { row ->
				String Vertragsnummer = row.FK_TBL_VERTRAG
				contractMap.add(Vertragsnummer);
			}
		}
		catch(Exception e)
		{
			d3.log.error("Fehler beim SQL Verbindungsaufbau: " + e);
		}
		finally
		{	
			if(lSQLConnection != null)
			{
				lSQLConnection.close();
			}
		}
		d3.log.info("Ende getContractWithMoreContractDocs");
	}
	
	/**
     * Function to log given message to log file and to console
     * @param message
     */
    void log(String message) {
        String messageWithTimestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(System.currentTimeMillis())) + " : ${message}"
        if(!constanten.logFile.exists()) {
            // check if directory exists
            // check if directory "Log" exists
            File logDir = new File(constanten.logDirPath)
            if(!logDir.exists() || !logDir.isDirectory()) {
                // create directory for log files
                logDir.mkdirs()
            }

            constanten.logFile.createNewFile()
        }
        constanten.logFile.append(messageWithTimestamp + "\n")
    }
	