package OWL2generator;

import java.sql.Connection;
/*
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
*/
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *  The <b><code>DBF_main</code></b> class serves as the core application logic
 *  within a Java framework for generating OWL/XML ontologies: It
 *  leverages text files containing configuration details to
 *  construct the ontology structure. This class acts as the
 *  central controller, directing the overall process of ontology
 *  generation based on user-provided configuration files.
 *  <p>
 *  <b>Key Functionalities:</b>
 *  <p>
 *  Processes Command Line Arguments: Evaluates user-provided
 *  arguments to determine the input/output directory for text
 *  files used during generation.
 *  <p>
 *  Controls Ontology Generation Sequence: Orchestrates the
 *  creation of the ontology by calling dedicated modules responsible for:
 *  <p>
 *  <ul>
 *  <li>Generating the OWL header
 *  <li>Defining class structures
 *  <li>Setting class disjointness
 *  <li>Defining object property triplets (relationships between individuals)
 *  </ul>
 *  <p>
 *  Manages Configuration Files: Employs separate text files for
 *  each generation step, allowing for modularity and customization.
 *  <p>
 *  Logs Console Messages: Provides informative messages during
 *  execution to track progress.
 *  <p>
 *  <b>Additional Notes:</b>
 *  <p>
 *  The class utilizes pre-defined file paths and comments within the
 *  code, suggesting potential improvements for user-configurable settings.
 *  <p>
 *  The comments indicate the framework's reliance on external classes.
 *  <p>
 *  <b>Environment:</b> 
 *  <ul>
 *  <li>    IDE:              Eclipse IDE for Java Developers
 *  <li>    Version:          2021-12 (4.22.0)
 *  <li>    Build id:         20211202-1639
 *  <li>    HW Model Name:    iMac, MacOS Monterey, 12.5.1
 *  <li>    Processor Name:   Quad-Core Intel Core i5
 *  <li>    Processor Speed:  3.2 GHz
 *  <li>    Memory:           32 GB 1867 MHz DDR3
 *  <li>    Disk:             APPLE SSD SM0256G    
 *  <li>    Serial:           DGKRC080GG7V
 *  </ul>
 *  @version 1-001
 *  @since   2024/05/28
 *  @author  Edit Hlaszny (https://www.edithlaszny.eu/) 
 */

public class DBFO_main 
{ 
	private final boolean htmlDocgenerationNeeded = true ;
	
    /**
     *  The output files should have a common directory where they are stored.
     */
    private String defaultIOdirName = "." ;

    /**
     *  Name of the JAR-file making the application stand alone runnable
     */
    //private final String runnableJarfile   = "owl2gen.jar" ;
	
    private       String OWLresultFile    = this.defaultIOdirName + "/OWL/SO_ontology.owl" ;
    private       String htmlResult       = this.defaultIOdirName + "/html/SO_ontology.html" ;

    /*
     *  MySQL DB-relevant definitions
     */
    private final String      DBurl        = "jdbc:mysql://localhost:3306/DBFOsociology";
    private final String      DBuser       = "root";
    private final String      DBpassword   = "root";
    private       Connection  DBconnection = null ;

    /*
     *  runtime calculation
     */
    private final RunTimeCalculator rtc = new RunTimeCalculator() ; 

    /*
     *  shared utilities    
     */
    private       SharedUtils shu          = new SharedUtils() ;

    /**
     *  In silent mode no log messages will be displayed
     */
    private final boolean silentMode      = false ;
    
	    /**
	     *  The main method starts the app.
	     *  
    	 *  @param args Java standard calling arguments 
	     */
    public static void main(String args[])
    {
	    new DBFO_main().generateOWL2ontology(args) ;
		
   	}   //  end of method main() 

    /**
     *  The method controls the sequence of the ontology generation. The app consists of 
     *  the following modules (each of them is controlled by the corresponding DB tables) 
     */
    private void generateOWL2ontology(String args[])
    {
        if (args.length == 1) 
        {
        	this.defaultIOdirName = args[0] ;
            this.OWLresultFile    = this.defaultIOdirName + "/OWL/SO_ontology.owl" ;
            this.htmlResult       = this.defaultIOdirName + "/html/SO_ontology.html" ;
        }

        String startTime = shu.getCurrTime() ; 
        log(  "DBFOschemafy V3-001 started" + " (" + startTime + ")\n") ;
        
        /**
         *  Establishing MySQL DB-connection
         */
        connectToDB() ;
        
            new ResetDBcounters(this.DBconnection) ; 

        	/**
        	 *  For functional investigation purposes:
        	 *  
        	 *      This class is responsible for generating html documentation 
        	 *      (e.g. drop down structures, classes, object properties, data 
        	 *      properties, n-ary casual relationships).
        	 *      
        	 *      Therefore, it creates the following classes which performs 
        	 *      the mentioned tasks:
        	 *       
             *          1) RelationsFetcher,
             *          2) CreateHtmlHeader,
             *          3) CreateHtmlHeaderDynamicPart,
             *          4) CreateHtmlHeader,
             *          5) CreateHTMLcollapsibleTrees,
             *          6) GenerateHtml_class_doc,
             *          7) DBFO_GenHtml_objProperties_doc,
             *          8) DBFO_GenHtml_dataProperties_doc,
             *          9) DBFO_GenHtml_n_ary_CasualRelationships,
             *         10) CreateHtmlTrailer
        	 */
            if (htmlDocgenerationNeeded)
                new GenerateHtml_doc(this.htmlResult, this.DBconnection) ;
        	else
                new GenerateNoHtml_doc(this.htmlResult, this.DBconnection) ;        		
            
            new WriteOWLHeader(this.OWLresultFile,
                               this.DBconnection) ;

            new WriteOWLHeaderAnnotations(this.OWLresultFile,
                                          this.DBconnection
                                         ) ;

            new WriteSKOSannotations(this.OWLresultFile,
                                    this.DBconnection
                                   ) ;

            new DeclareClasses(this.OWLresultFile,
                               this.DBconnection
                              ) ;

            new DeclareSubclasses(this.OWLresultFile,
                                  this.DBconnection
                                 ) ;
            /**
             *           
             *  Removing sibling class disjointness:
             *
             *      Sibling class disjointness relationships can be totally 
             *      removed. Therefore 'SO_upload_05_disjoint_classes.sql' 
             *      should also be removed from ./cmd/copyAndRename.sh
             */ 
            new DeclareDisjointClasses(this.OWLresultFile,
                                       this.DBconnection
                                      ) ;
                                       
            new AnnotateClasses(this.OWLresultFile,
                                this.DBconnection
                               ) ;

        	new DBFO_GenOWL_objProperties(this.OWLresultFile,
                                          this.DBconnection
                                         ) ;

        	new DBFO_GenOWL_dataProperties(this.OWLresultFile,
                                           this.DBconnection
                                          ) ;

        	new DBFO_GenOWL_n_ary_CasualRelationships(this.OWLresultFile, //  result file name 
                                                      this.DBconnection
                                                     ) ;
            new WriteOWLTrailer(this.OWLresultFile,
                                this.DBconnection) ;
        	
            String endTime = shu.getCurrTime() ; 
            String runTime = rtc.formatRuntimeToSec(rtc.calculateRuntime(startTime, endTime)) ;
            
            log(  "Total runtime: " + runTime + " sec.\n"
                + "DBFOschemafy V3-001 has succesfully been completed"
            	+ " (" + endTime + ")\n") ;

            System.exit(0);
          
    }   //  and of method generateOWL2ontology()

    private void connectToDB()
    {
        DBserverConnection DC = new DBserverConnection() ;
        
        DC.connectDB(this.DBurl, this.DBuser, this.DBpassword) ;
        
        this.DBconnection = DC.getDBconnector() ;

    }   //  end of method connectToDB()
    
    /**
     *  Writes text message to the console   
     *  @param logEntry displayed message    
     */
    public void log(String logEntry)
    {
        /*
        
        The param logEntry layout:
    
        <logEntry> ::= <spaces> <action> <spaces> <numericString> <spaces> <comment>
            <spaces> ::= <spaces> | <spaces> <space>
                <space> ::= { " "}
            <action> ::= { string_max_12_length_string }
            <numericString> ::= { ASCII_string_of_numeric_chars_max_length_is_12 }
            <comment> :: = { string_in_any_length }
    
        The displayed layout:
    
        <logEntry> ::= <action> { two_spaces } <formatted_numericString> { one_spaces } <comment>
            <action> ::= { string_max_12_length_string }
            <formatted_numericString> ::= { comme_separated_right_justified_numeric_string }
            <comment> :: = { string_in_any_length }
        */
    	
        if (!this.silentMode)
        {  
        	if (logEntry.charAt(0) == ' ')
        	{
        	    Pattern LINE           = Pattern.compile("^\\s*([^\\s]{1,12})\\s+([0-9]{1,12})\\s+(.*)$");
        	    int NUMBER_FIELD_WIDTH = 6;
        	    
    	        String[] lines = logEntry.split("\\R", -1);
    	        for (String line : lines) 
    	        {
    	            Matcher m = LINE.matcher(line);
    	            if (m.matches()) {
    	                String action = m.group(1);
    	                String numStr = m.group(2);
    	                String comment = m.group(3);

    	                try 
    	                {
    	                    long n = Long.parseLong(numStr);
    	                    String withCommas = String.format(Locale.US, "%,d", n);
    	                    
    	                    System.out.println("    " + action + "  " 
    	                            + String.format("%" + NUMBER_FIELD_WIDTH + "s", withCommas)
    	                            + " " + comment);
    	                } 
    	                catch (NumberFormatException e) 
    	                {
    	                    System.out.println("NumberFormatException" + e); // fallback unchanged
    	                }
    	            } 
    	            else 
    	            {
    	                ;  //  non-matching lines ignored
    	            }
    	            
    	        }   //  end of for loop
        	}	
            else
        	{
                System.out.print(logEntry) ;
        	}
        }
        
    }   //  end of log()
 
}   //  end of class OWL2_Generator
