
// (1) Global d.3 libraries
import com.dvelop.d3.server.core.D3Interface
import com.dvelop.d3.server.Document
import com.dvelop.d3.server.User
import com.dvelop.d3.server.Condition
import com.dvelop.d3.server.DocumentType
import groovy.sql.GroovyRowResult

import com.dvelop.d3.server.ValueSet
import com.dvelop.d3.server.RepositoryField

import java.sql.Timestamp
import java.util.Calendar
import java.text.SimpleDateFormat

// Libraries to handle the different hook types
import com.dvelop.d3.server.Entrypoint

public class proz01_prozessakte {
    boolean logging = true;

	private static int POS_AZ 			= 1;
	private static int POS_Jahr 		= 2;
	private static int POS_StatZ		= 3;
	private static int POS_GerichtAZ	= 4;
	private static int POS_Klaeger 		= 9;
	private static int POS_Zda			= 13;
	private static int POS_Beklaeger	= 15;
	private static int POS_AusArt		= 23;
	private static int POS_DokGrp	 	= 30;
	private static int POS_DokTyp 		= 31;
	private static int POS_AusDat 		= 51;
	private static int POS_ZLM			= 35;
	private static int POS_LOESCHGRD	= 36;
	private static int POS_GADRESSE		= 33;
	private static int POS_Gericht		= 20;
	private static int POS_DOKIDORG		= 10;
	private static int POS_DOKDAT       = 55;
	// Feldpostitionen Adressverwaltung
	private static int POS_FFOE			= 2;
	private static int POS_Name			= 9;
	private static int POS_Strasse		= 21;
	private static int POS_Hnr			= 29;
	private static int POS_Plz			= 24;
	private static int POS_Ort			= 25;
	
	private static String WM_TRENNZEICHEN	= ";";
	
	// Variablen - Aufbewahrungsfristen (in Jahren)
	private static int FRIST_AUSSONDERUNG	= 10;		// 10 Jahre
	private static int STATUS_ZDA			= 0;
	private static int NEUES_AZ				= 0;
	private static int CHANGE_GERICHT		= 0;

	// Datenbanktabelle
	private static String TB_DokGrpTyp		= "DV_PROZ_Doktyp";
	
	private static String G01_DS_PROZESSA	= "APROZ";
	private static String G01_DS_PROZESSD	= "DPROZ";
	private static String G01_DS_ORGANI		= "DPROZ";
	
	
	// Offenbar eigentlich zentral abzulegen
	
	private static String G01_STR_JA	= "Ja";
    private static String G01_STR_NEIN	= "Nein";
    
	
	@Entrypoint( entrypoint = "hook_insert_entry_10" )
    public int hook_insert_entry_10(D3Interface d3, User user, DocumentType docType, Document doc)
    {	
		
		!logging ?: d3.log.info(" hook_insert_entry_10: Anfang")
		proz01_split_AZ( 1, doc, d3 );
		proz01_split_Gericht( doc, d3 );
		!logging ?: d3.log.info(" hook_insert_entry_10: Ende")
		
		return 0;
	}
	
	
	@Entrypoint( entrypoint = "hook_insert_exit_10" )
	public int hookInsertExit10 (D3Interface d3, Document doc, String fileDestination, Integer importOk, User user, DocumentType docType)
	{
		!logging ?: d3.log.info("START | hookInsertExit10 ");
		
		if ( docType == G01_DS_PROZESSA )
		{
			proz01_fill_AZ_Nummer( 0, doc, d3 );
		}
		
		
		!logging ?: d3.log.info("ENDE | hookInsertExit10 ");
		return 0;
	}
	
	
	@Entrypoint( entrypoint = "hook_upd_attrib_entry_20" )
	public int hookUpdAttribEntry20(D3Interface d3, Document doc, User user, DocumentType docType, DocumentType docTypeNew)
	{
		d3.log.info("START | hookUpdAttribEntry20")

		// temporäres Objekt holen, um zu prüfen, das sich Eigenschaften geändert haben
		def oldDocAttributes = d3.archive.getDocument(doc.id());
		//d3.log.error( "1 Dokumentart: " + docType.id() );
		//d3.log.error( "1 Gericht (" + POS_Gericht + "): " + doc.field[ POS_Gericht ] + " ll " + oldDocAttributes.field[ POS_Gericht ] );
		//d3.log.error( "1 Adresse (" + POS_GADRESSE + "): " + doc.field[ POS_GADRESSE ] + " ll " + oldDocAttributes.field[ POS_GADRESSE ] );
		
		if ( docType.id() == G01_DS_ORGANI )
		{
			if ( doc.field[ POS_Name ] != oldDocAttributes.field[ POS_Name ] )
			{
				CHANGE_GERICHT = 1;
			}
			
			if ( doc.field[ POS_Strasse ] != oldDocAttributes.field[ POS_Strasse ] )
			{
				CHANGE_GERICHT = 1;
			}
			
			if ( doc.field[ POS_Hnr ] != oldDocAttributes.field[ POS_Hnr ] )
			{
				CHANGE_GERICHT = 1;
			}
			
			if ( doc.field[ POS_Plz ] != oldDocAttributes.field[ POS_Plz ] )
			{
				CHANGE_GERICHT = 1;
			}
			
			if ( doc.field[ POS_Ort ] != oldDocAttributes.field[ POS_Ort ] )
			{
				CHANGE_GERICHT = 1;
			}
			
			d3.log.error( "hookUpdAttribEntry20 " + CHANGE_GERICHT );
			
		}
		else
		{
			proz01_split_AZ( 1, doc, d3 );
			proz01_split_Gericht( doc, d3 );
			
			if ( doc.field[ POS_Zda ] != oldDocAttributes.field[ POS_Zda ] )
			{
				STATUS_ZDA = 1;
			}
			
			// Wenn das Feld zum Löschen markiert auf Ja gesetzt wurde, überprüfe ob beim Löschgrund etwas eingetragen wurde. Falls nicht, gebe eine Fehlermeldung aus.
			// Wenn das Feld zum Löschen markiert auf Nein gesetzt wurde, dann leere das Feld Löschgrund
			
			if ( doc.field[ POS_ZLM ] != oldDocAttributes.field[ POS_ZLM ] )
			{
				if ( doc.field[ POS_ZLM ] == G01_STR_JA )
				{
					if ( doc.field[ POS_LOESCHGRD ] == "" )
					{
						return -403;
					}
				}
				else if ( doc.field[ POS_ZLM ] == G01_STR_NEIN )
				{
					doc.field[ POS_LOESCHGRD ] = "";
				}
			}
		}
		
		if ( ( docType.id() == G01_DS_PROZESSA ) && ( doc.field[ POS_Jahr ] != oldDocAttributes.field[ POS_Jahr ] ) )
		{
			NEUES_AZ = 1;
		}
		
		d3.log.error( "2 Dokumentart: " + docType.id() );
		d3.log.error( "2 Gericht (" + POS_Gericht + "): " + doc.field[ POS_Gericht ] + " ll " + oldDocAttributes.field[ POS_Gericht ] );
		d3.log.error( "2 Adresse (" + POS_GADRESSE + "): " + doc.field[ POS_GADRESSE ] + " ll " + oldDocAttributes.field[ POS_GADRESSE ] );
		
		if ( ( docType.id() == G01_DS_PROZESSA ) && ( ( doc.field[ POS_Gericht ] != oldDocAttributes.field[ POS_Gericht ] ) || ( doc.field[ POS_GADRESSE ] != oldDocAttributes.field[ POS_GADRESSE ] ) ) )
		{
			def sqlQuery = "SELECT dok_dat_feld_" + POS_Name + " POS_Name, dok_dat_feld_" + POS_Strasse + " POS_Strasse, dok_dat_feld_" + POS_Hnr + " POS_Hnr, dok_dat_feld_" + POS_Plz + " POS_Plz, dok_dat_feld_" + POS_Ort + " POS_Ort FROM firmen_spezifisch WHERE kue_dokuart = 'AAORG' AND dok_dat_feld_" + POS_Name + " = '" + doc.field[POS_Gericht] + "'";
			
			def ergebnis = d3.sql.executeAndGet( sqlQuery );
			//d3.log.error( "Name: " + ergebnis[ 0 ].POS_Name );
			//d3.log.error( "POS_Strasse: " + ergebnis[ 0 ].POS_Strasse );
			//d3.log.error( "POS_Hnr: " + ergebnis[ 0 ].POS_Hnr );
			//d3.log.error( "POS_Plz: " + ergebnis[ 0 ].POS_Plz );
			//d3.log.error( "POS_Ort: " + ergebnis[ 0 ].POS_Ort );
			
			
			
			
			if ( ( ergebnis[ 0 ].POS_Name == "" ) || ( ergebnis[ 0 ].POS_Strasse == "" ) || ( ergebnis[ 0 ].POS_Hnr == "" ) || ( ergebnis[ 0 ].POS_Plz == "" ) || ( ergebnis[ 0 ].POS_Ort == "" ) )
			{
				//Gerichtsdaten nicht gepflegt! Bitte in der Organisation pflegen.
				return -569;
			}
			
			def Gerichtsadresse = ergebnis[ 0 ].POS_Strasse + " " + ergebnis[ 0 ].POS_Hnr + ", " + ergebnis[ 0 ].POS_Plz + " " + ergebnis[ 0 ].POS_Ort;
			
			if ( Gerichtsadresse != doc.field[ POS_GADRESSE ] )
			{
				//Gerichtsadresse entspricht nicht dem aktuell ausgewählten Gericht!
				return -570;
			}
			
		}
		
		
		
		
		
		
		d3.log.info("ENDE | hookUpdAttribEntry20")
		return 0;
	}

	
	@Entrypoint( entrypoint = "hook_upd_attrib_exit_20" )
	public int hookUpdAttribExit20(D3Interface d3, Document doc, Integer errorCode, User user, DocumentType docType, DocumentType docTypeOld)
	{
		d3.log.info("START | hookUpdAttribExit20 ")
		
		def strZDA, strDatum;
		
		if ( ( NEUES_AZ == 1 ) && ( docType != G01_DS_ORGANI ) )
		{
			NEUES_AZ = 0;
			proz01_fill_AZ_Nummer( doc, d3, 1 );
		}
		
		
		
		if ( ( STATUS_ZDA == 1 ) && ( docType != G01_DS_ORGANI ) )
		{
			STATUS_ZDA = 0;
			
			if ( doc.field[ POS_Zda ] == G01_STR_JA )
			{
				strZDA = G01_STR_JA;
				strDatum = proz01_getAussonderungsdatum( FRIST_AUSSONDERUNG );
			}
			else
			{
				if ( doc.field[ POS_Zda ] == G01_STR_NEIN )
				{
					strZDA = G01_STR_NEIN;
					strDatum = "";
				}
				
			}
			
			// hier wird das docSearchCreate übernommen; dafür gibt es aber aktuell keine Entsprechung in Groovy.
			// das wird in Groovy direkt umgesetzt; d.h. man macht das manuell, was der JPL-Massenänderungs-Code en gros macht:
			
			def massen_sql = "select doku_id from firmen_spezifisch where ( kue_dokuart = '" + G01_DS_PROZESSA + "' or kue_dokuart = '" + G01_DS_PROZESSD + "' ) and dok_dat_feld_" + POS_AZ + " = '" + doc.field(POS_AZ) + "'";
			
			def massen_ergebnis = d3.sql.executeAndGet( massen_sql );
			
			if ( massen_ergebnis.size() > 0 )
			{
				int i;
				for ( i = 0 ; i < massen_ergebnis.size(); i++ )
				{
					def updateDoc = d3.archive.getDocument( massen_ergebnis[ i ].doku_id );
					
					updateDoc.field[ POS_Zda    ] = strZDA;
					updateDoc.field[ POS_AusDat ] = strDatum;
					updateDoc.field[ POS_AusArt ] = doc.field[ POS_AusArt ];
					updateDoc.updateAttributes( "Master" );
				}
			}
			
			if ( CHANGE_GERICHT == 1 && docType == G01_DS_ORGANI )
			{
				CHANGE_GERICHT = 0;
				
				def m_sql2 = "SELECT dok_dat_feld_" + POS_Name + " name, dok_dat_feld_" + POS_Strasse + " strasse, dok_dat_feld_" + POS_Hnr + " hnr, dok_dat_feld_" + POS_Plz + " plz, dok_dat_feld_" + POS_Ort + " ort	FROM firmen_spezifisch WHERE kue_dokuart = 'AAORG' AND doku_id = '" + doc.id + "'";
				
				def me2 = d3.sql.executeAndGet( m_sql2 );
				
				if ( me2.size() == 1 )
				{
					def strGAdresse = me2[ 0 ].strasse + " " + me2[ 0 ].hnr + " " + me2[ 0 ].plz + " " + me2[ 0 ].ort;
					
					m_sql3 = "select doku_id from firmen_spezifisch where kue_dokuart = '" + G01_DS_PROZESSA + "' and dok_dat_feld_" + POS_DOKIDORG + " = '" + doc.id + "'";
					
					def me3 = d3.sql.executeAndGet( m_sql1 );
					
					if ( me3.size()  > 0 )
					{
						def ud2 = d3.archive.getDocument( me3[ i ].doku_id );
						
						ud2.field[ POS_GADRESSE ] = strGAdresse;
						ud2.field[ POS_Gericht ] = me2[ 0 ].name;
						
						ud2.updateAttributes( "Master" );
						
					}
					
				}
				
			}
			
			
			
			
		}
		
		d3.log.info("ENDE | hookUpdAttribExit20 ")
		return 0;
	}
	
	
	@Entrypoint( entrypoint = "hook_validate_update_entry_10" )
	public int hookValidateUpdateEntry10(D3Interface d3, User user, DocumentType docType, Document doc, String nextcall) {
		d3.log.error("START | hookValidateUpdateEntry10 ");
		
		proz01_split_AZ( 1, doc, d3 );
		proz01_split_Gericht( doc, d3 );
		
		d3.log.error("ENDE | hookValidateUpdateEntry10 ");
		return 0;
	}
	
	
	@Entrypoint( entrypoint = "hook_search_entry_10" )
	public int hookSearchEntry10(D3Interface d3, User user, DocumentType docType, Document searchContext) {
		d3.log.error("START | hookSearchEntry10 ");
		
		proz01_split_AZ( 0, searchContext, d3 );
		proz01_split_Gericht( searchContext, d3 );
		
		d3.log.error("ENDE | hookSearchEntry10 ");
		return 0;
	}
	
	
	
	
	
	
	
	
	///////////////////////////////////////
	// Wertemengenhooks
	///////////////////////////////////////
	
	
	@ValueSet( entrypoint = "proz01_fill_Klaeger" )
	def proz01_fill_Klaeger( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc )
	{
		def where = "";
		
		if ( doc.field[ POS_Klaeger ] != null )
		{
			if ( doc.field[ POS_Klaeger ].length() >= 3 )
			{
				where = " AND (dok_dat_feld_" + POS_AZ + " LIKE '%" + doc.field[ POS_Klaeger ] + "%' OR dok_dat_feld_" + POS_Klaeger + " LIKE '%" + doc.field[ POS_Klaeger ] + "%')";
			}
		}
		
		def sqlStatement = "SELECT DISTINCT top 1000 dok_dat_feld_" + POS_AZ + " feld_1, dok_dat_feld_" + POS_Klaeger + " feld_2, dok_dat_feld_" + POS_GerichtAZ + " feld_3 FROM firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "' " + where;
		
		def resultRows = d3.sql.executeAndGet( (String) sqlStatement );
	
		if ( resultRows.size() > 0 )
		{
			reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 + ";" + it.feld_2 + ";" + it.feld_3 } );
		}
	}
	
	
	@ValueSet( entrypoint = "proz01_fill_Beklagter" )
	def proz01_fill_Beklagter( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc )
	{
		def where = "";
		
		if ( doc.field[ POS_Beklaeger ] != null )
		{
			if ( doc.field[ POS_Beklaeger ].length() >= 3 )
			{
				where = " AND (dok_dat_feld_" + POS_Beklaeger + " LIKE '%" + doc.field[ POS_Beklaeger ] + "%' )";
			}
		}
		
		def sqlStatement = "SELECT DISTINCT top 1000 dok_dat_feld_" + POS_Beklaeger + " feld_1 FROM firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "'" + where;
		
		def resultRows = d3.sql.executeAndGet( (String) sqlStatement );
	
		if ( resultRows.size() > 0 )
		{
			reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 } );
		}

	}
	
	
	@ValueSet( entrypoint = "proz01_WM_DOKGRP" )
	def proz01_WM_DOKGRP( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc )
	{
		def where = "";
		
		if ( ( doc.field[ POS_DokTyp ] != "" ) && ( doc.field[ POS_DokTyp ] != null ) && ( doc.field[ POS_DokTyp ] != "null" ) )
		{
			where = " where Dokumenttyp = '" + doc.field[ POS_DokTyp ] + "'";
		}
		
		def sqlStatement = "select distinct Dokumentgruppe from " + TB_DokGrpTyp;
		
		def resultRows = d3.sql.executeAndGet( (String) sqlStatement );
	
		if ( resultRows.size() > 0 )
		{
			reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumentgruppe } );
		}
	}
	
	
	@ValueSet( entrypoint = "proz01_WM_DOKTYP" )
	def proz01_WM_DOKTYP( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc )
	{
		def where = "";
		
		if ( ( doc.field[ POS_DokGrp ] != "" ) && ( doc.field[ POS_DokGrp ] != null ) && ( doc.field[ POS_DokGrp ] != "null" ) )
		{
			where = " where Dokumentgruppe = '" + doc.field[ POS_DokGrp ] + "'";
		}
		
		def sqlStatement = "select distinct Dokumenttyp from " + TB_DokGrpTyp + where;
		
		def resultRows = d3.sql.executeAndGet( (String) sqlStatement );
		
		d3.log.error( sqlStatement );
		
		if ( resultRows.size() > 0 )
		{
			reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumenttyp } );
		}
	}
	
	
	@ValueSet( entrypoint = "proz01_getGericht" )
	def proz01_getGericht( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc )
	{
		def where = "";
		
		if ( doc.field[ POS_Gericht ] != null )
		{
			if ( doc.field[ POS_Gericht ].length() >= 3 )
			{
				where = " AND dok_dat_feld_" + POS_Name + " LIKE '%:" + doc.field[ POS_Gericht ] + "%' ";
			}
		}
		
		def sqlQuery = "SELECT fs.dok_dat_feld_" + POS_Name + " feld_1, fs.dok_dat_feld_" + POS_Strasse + " feld_2, fs.dok_dat_feld_" + POS_Hnr + " feld_3, fs.dok_dat_feld_" + POS_Plz + " feld_4, fs.dok_dat_feld_" + POS_Ort + " feld_5, fs.doku_id \
			FROM firmen_spezifisch fs \
			LEFT JOIN benutzergruppen gruppe \
			ON gruppe.benutzergruppe = fs.dok_dat_feld_" + POS_FFOE + " \
			Left JOIN benutzer_in_gruppe bInGrp \
			ON gruppe.gruppen_id = bInGrp.benutzergruppe \
			WHERE fs.kue_dokuart = 'AAORG' AND  (bInGrp.benutzername = '" + user + "' OR fs.dok_dat_feld_" + POS_FFOE + " IS NULL) " + where;
		
		
		def resultRows = d3.sql.executeAndGet( (String) sqlQuery );
		
		if ( resultRows.size() > 0 )
		{
			reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 + "|" + it.feld_2 + "|" + it.feld_3 + "|" + it.feld_4 + "|" + it.feld_5 + "|" + it.doku_id } );
		}
	}
	
	
	
	
	
	///////////////////////////////////////
	// Arbeitsfunktionen
	///////////////////////////////////////
	
	
	//////////////////// proz01_split_AZ /////////////////////////////////////////////////
	// Funktion zum Aufteilen des Feldes Aktenzeichen nach AZ;Klaeger;Gerichtszeichen
	// und fuellen in die jeweiligen Felder
	//////////////////////////////////////////////////////////////////////////////////

	public void proz01_split_AZ( int NotSearch, Document doc, D3Interface d3 )
	{
		def strKlaeger = doc.field[ POS_Klaeger ].toString();
		
		if ( strKlaeger != null )
		{
			def erg = strKlaeger.tokenize( WM_TRENNZEICHEN );
			
			if ( erg.size() > 2 )
			{
				doc.field[ POS_Klaeger ] = "";
				doc.field[ POS_AZ      ] = erg[ 0 ];
				
				if ( NotSearch == 1 )
				{
					doc.field[ POS_Klaeger   ] = erg[ 1 ];
					doc.field[ POS_GerichtAZ ] = erg[ 2 ];
				}
			}
		}
	}
	
	
	
	/////////////////////////// proz01_fill_AZ_Nummer //////////////////////////////////////
	//
	//////////////////////////////////////////////////////////////////////////////////////

	public void proz01_fill_AZ_Nummer( Document doc, D3Interface d3, int update )
	{
		
		def treffer;
		def strNummer;
		
		if ( update == 0 )
		{
			def sqlQuery = "SELECT TOP (1) right(dok_dat_feld_" + POS_AZ + ", 4) + 1 nummero_uno from firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "' ORDER BY right(dok_dat_feld_" + POS_AZ +" ,4) DESC ";
			
			treffer = d3.sql.executeAndGet( (String) sqlQuery );
			
			strNummer = doc.field[ POS_Jahr ] + "-" + (String) treffer[ 0 ].nummero_uno.padLeft( 4, '0' );
			
		}
		else
		{
			if ( update == 1 )
			{
				if ( doc.field[ POS_AZ ] != null )
				{
					def docfield_pos_az = doc.field[ POS_AZ ].toString();
					
					def tok = docfield_pos_az.tokenize( "-" );
					if ( tok.size() > 1 )
					{
						strNummer = doc.field[ POS_Jahr ] + "-" + tok.get(2);
					}
				}
			}	
		}
		
		def currentDoc = d3.archive.getDocument( doc.id );
		currentDoc.field[ POS_AZ ] = strNummer;
		currentDoc.updateAttributes( "Master" );
		
		// Update-Call returniert nichts definitiv Verwertbares, daher wird keine Logmeldung ausgegeben (anders als im JPL-Code).
		
	}
	
	
	
	//////////////////// l01_split_Gericht /////////////////////////////////////////////////
	// Funktion zum Aufteilen des Felds Aktenzeichen nach AZ;Klaeger;Gerichtszeichen
	// und fuellen in die jeweiligen Felder
	//////////////////////////////////////////////////////////////////////////////////
	
	public void proz01_split_Gericht( Document doc, D3Interface d3 )
	{
		def strGericht = doc.field[ POS_Gericht ].toString();
		
		if ( strGericht != null )
		{
			def erg = strGericht.tokenize( "|" );
			
			if ( erg.size() > 1 )
			{
				doc.field[ POS_Gericht  ] = erg[ 0 ];
				doc.field[ POS_GADRESSE ] = erg[ 1 ] + " " + erg[ 2 ] + ", " + erg[ 3 ] + " " + erg[ 4 ];
				doc.field[ POS_DOKIDORG ] = erg[ 5 ];
			}
		}
	}
	
	
	
	//////////////////// proz01_getAussonderungsdatum /////////////////////////////////////////////////
	// Liefert das Aussonderungsdatum anhand einer Frist
	// Parameter: iFrist - Aufbewahrungsfrist
	//////////////////////////////////////////////////////////////////////////////////
	
	public String proz01_getAussonderungsdatum( String iFrist )
	{
		def ergebnis = "";
		
		Date date = new Date();
		
		int dateYear = date.format( "yyyy" );
		
		ergebnis = dateYear + iFrist;
		
		return "31.12." + ergebnis;
		
	}
	
	
	
	
}
