package OWLpreprocessing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;

// import OWL2generator.DBserverConnection;

public class OWL_Main 
{
	/*
	 *  should be the DB refreshed by this project, or detached
	 *  refreshing is needed (RefreshDB project can do that)
	 */
    private final boolean    refreshDB    = false ;
	
    /*
     *  MySQL DB-relevant definitions
     */
	private final String     DBname       = "DBFOsociology"  ; 
    private final String     DBurl        = "jdbc:mysql://localhost:3306/DBFOsociology";
    private final String     DBuser       = "root";
    private final String     DBpassword   = "root";
    private       Connection DBconnection = null ;
	
    private String dirBase = "." ;
    private String inputDir  = dirBase + "/input/" ;
    private String outputDir = dirBase + "/output/" ;

    /*
     *  OWLpreprocessor-relevant definitions
     */
	private  String BFO_htmlTree               = outputDir + "SO_upload_10_BFO_Tree.sql.txt" ;
	private  String BFO_inputTree              = inputDir  + "BFOmapping/BFO_tree_struct.txt";
	private  String BFOmapping                 = inputDir  + "BFO_ClassMapping.txt" ;
	private  String BFOsubClasses              = outputDir + "SO_upload_05_BFO_subclasses.sql.txt" ;
	private  String classAnnotations           = inputDir  + "OWLclassAnnotations.txt"  ; 
	private  String classAnnotationsSQL        = outputDir + "SO_upload_07_class_annotations.sql.txt" ;
	private  String classesSubclasses          = outputDir + "SO_upload_04_owl_classes.sql.txt" ;
	private  String classStructure             = BFOmapping ;
	private  String dataPropertyDefs           = inputDir  + "dataPropertyDefinitions.txt" ;
	private  String dataPropertySQLdefs        =  outputDir + "SO_upload_16_dataProperties.sql.txt" ;
	private  String dataPropertyTreeSQLdefs    = outputDir + "SO_upload_17_dataProp_Tree.sql.txt" ;
	private  String disjointClasses            = outputDir + "SO_upload_06_disjoint_classes.sql.txt" ;
	private  String header_SQL                 = outputDir + "SO_upload_01_XMLheader.sql.txt" ;
	private  String header_txt                 = inputDir  + "ontologyHeader.txt" ;
	private  String headerAnnotations_SQL      = outputDir + "SO_upload_02_headerAnnotations.sql.txt" ;
	private  String headerAnnotations_txt      = inputDir  + "ontologyHeaderAnnotations.txt" ;
	private  String HtmlHeaderCommandsIN_1_txt = inputDir  + "html/header_session_A.txt" ;
	private  String HtmlHeaderCommandsIN_2_txt = inputDir  + "html/header_session_B.txt" ;
	private  String HtmlHeaderCommandsOUT_SQL  = outputDir + "SO_upload_08_HTMLheader.sql.txt" ;
	private  String HtmlTrailerCommandsIN_txt  = inputDir  + "html/trailer.txt" ;
	private  String HtmlTrailerCommandsOUT_SQL = outputDir + "SO_upload_09_HTMLtrailer.sql.txt" ;
	private  String inverseObjProperties       = outputDir + "SO_upload_13_invObjProp.sql.txt" ;
	private  String n_ary_data_assertions_SQL  = outputDir + "SO_upload_20_n_ary_data_assertions_SQL.sql.txt" ;
	private  String n_ary_participants_SQL     = outputDir + "SO_upload_19_n_ary_participants_SQL.sql.txt" ;
	private  String n_ary_relations_SQL        = outputDir + "SO_upload_18_n_ary_relations_SQL.sql.txt" ;
	private  String objPropertyAnnotations     = outputDir + "SO_upload_12_objPropAnn.sql.txt" ;
	private  String objPropertyAttributes      = inputDir  + "objectPropertyAttributes.txt" ;
	private  String objPropertyDefs            = inputDir  + "objectPropertyDefinitions.txt" ;
	private  String objPropertyTree            = outputDir + "SO_upload_15_objProp_Tree.sql.txt" ;
	private  String relationDefs_TXT           = inputDir  + "relationDefinitions.txt"  ;
	private  String SKOSAnnotations_SQL        = outputDir + "SO_upload_03_skosAnnotations.sql.txt" ;
	private  String SKOSAnnotations_txt        = inputDir  + "skosAnnotationProperties.txt" ;
	private  String SO_htmlTree                = outputDir + "SO_upload_11_SO_Tree.sql.txt" ;
	private  String SO_inputTree               = BFOmapping ;
	private  String superObjProperties         = outputDir + "SO_upload_14_superObjProp.sql.txt" ;
	private  String trailer_SQL                = outputDir + "SO_upload_99_XMLtrailer.sql.txt" ;
	private  String trailer_txt                = inputDir  + "ontologyTrailer.txt" ;

	/*
     *  runtime calculation
     */
    private final RunTimeCalculator       rtc      = new RunTimeCalculator() ; 
	
	/**
     *  In silent mode no log messages will be displayed
     */
    private       OWL_BufferedWriterUtils bwu      = new OWL_BufferedWriterUtils() ;

	public static void main(String[] args)
    {
		new OWL_Main().preprocessing(args) ;

	//	System.exit(-1);
		
    }   //  end of method main()

	private void preprocessing(String[] args)
	{
        if (args.length == 1)
		{
        	this.dirBase = args[0] ;
        	resetFilenames() ;
		}
        
        /**
         *  Logging the start of preprocessing
         */
         String startTime = rtc.getCurrTime() ; 
         bwu.log(  "\nOWL preprocessing started" + " (" + startTime + ")\n") ;
		
        /**
         *  Establishing MySQL DB-connection
         */
        connectToDB() ;

     	new OWL_CreaOntologyHeader(this.DBname,     //  Database name
     			                   this.header_txt, //  txt input
     			                   this.header_SQL  //  SQL output
                                  ) ;

    	new OWL_CreaHeaderAnnotations(this.DBname,                //  Database name
    			                      this.headerAnnotations_txt, //  txt input
    			                      this.headerAnnotations_SQL  //  SQL output
                                     ) ;

    	
    	new OWL_DeclareSKOSannotationProperties(this.DBname,              //  Database name
    			                                this.SKOSAnnotations_txt, //  txt input
    			                                this.SKOSAnnotations_SQL  //  SQL output
                                               ) ;

    	new OWL_CreaSubclassesAndDisjunctness(this.DBname,            //  Database name
    			                              this.classStructure,    // txt input
    			                              this.classesSubclasses, // SQL output
    			                              this.disjointClasses    // SQL output
    	  	                                 ) ;
    	
    	new OWL_CreaBFOclassMapping(this.DBname,       //  Database name
    			                    this.BFOmapping,   //  txt input
    			                    this.BFOsubClasses //  SQL output
    	                           ) ;

    	new OWL_CreaOWLclassAnnotation(this.DBname,             //  Database name
    			                       this.classAnnotations,   //  txt input
    			                       this.classAnnotationsSQL //  SQL output
				                      ) ; 

		
     	new OWL_CreaOntologyTrailer(this.DBname,      //  Database name
     			                    this.trailer_txt, //  txt input
     			                    this.trailer_SQL  //  SQL output
                                   ) ;
    	
        new OWL_CreaHtmlHeader(this.DBname,
        		               this.HtmlHeaderCommandsIN_1_txt, 
        		               this.HtmlHeaderCommandsIN_2_txt, 
        		               this.HtmlHeaderCommandsOUT_SQL
        		              ) ;
       	
        new OWL_CreaHtmlTrailer(this.DBname,
        		                this.HtmlTrailerCommandsIN_txt, 
        		                this.HtmlTrailerCommandsOUT_SQL
        		               ) ;
        
    	new OWL_CreaObjectPropertyData(this.DBname,
    		                           this.objPropertyDefs,
    		                           this.objPropertyAttributes,
    		                           this.objPropertyAnnotations,
    		                           this.inverseObjProperties,
    		                           this.superObjProperties
    		                          ) ;
    	
        new OWL_CreaBFO_CollapsibleTree(this.DBname,
        		                        this.BFO_inputTree,
        		                        this.BFO_htmlTree) ; 
        
        new OWL_CreaSOcollapsibleTree(this.DBname,
        		                      this.SO_inputTree,
        		                      this.SO_htmlTree) ; 
        
        new OWL_CreaObjectProperty_CollapsibleTree(this.DBname,
        		                                   this.objPropertyDefs,
        		                                   this.objPropertyTree
        		                                  ) ;
        
        new OWL_CreaDataProperty_CollapsibleTree(this.DBname,
        		                                 this.dataPropertyDefs,
        		                                 this.dataPropertyTreeSQLdefs
        		                                ) ;
       
        
        new OWL_RelationEvaluator (this.DBconnection ,
        		                   this.DBname , 
        		                   this.relationDefs_TXT ,
        		                   this.n_ary_relations_SQL ,
        		                   this.n_ary_participants_SQL ,
        		                   this.n_ary_data_assertions_SQL
    	                          ) ;
        
        new OWL_DataPropertyEvaluator(this.DBname,
        		                      this.dataPropertyDefs, 
        		                      this.dataPropertySQLdefs
        		                     ) ;
         		            
        if (this.refreshDB)
        {
            try { execCommand("./cmd/copyAndRename.sh") ; }
            catch(InterruptedException e) { e.printStackTrace() ; }
        }

        /**
         *  Logging of the result
         */
        String endTime = rtc.getCurrTime() ; 
        String runTime = rtc.formatRuntimeToSec(rtc.calculateRuntime(startTime, endTime)) ;
        
        bwu.log(  "Total runtime: " + runTime + " sec.\n"
                + "OWL preprocessing has succesfully been completed"
        	    + " (" + endTime + ")\n") ;
        
	}   //  end of method preprocessing()

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

    }   //  end of method connectToDB()
    
    private void execCommand(String cmd) throws InterruptedException
    {
        try
        {
            ProcessBuilder pb = new ProcessBuilder(cmd) ;

            //  merge stdout and stderr
            pb.redirectErrorStream(true) ;

            Process process = pb.start();

            //  read the output
            try (BufferedReader reader = 
                 new BufferedReader(new InputStreamReader(process.getInputStream()))) 
            {
                String line;
                while ((line = reader.readLine()) != null) 
                {
                    System.out.println(line);
                }
            }
        } 
        catch(IOException e)
        {
            e.printStackTrace() ;
        }
        
    }   //  end of method execCommand()

    private void resetFilenames()
    {
        this.inputDir                   = this.dirBase + "/input/" ;
        this.outputDir                  = this.dirBase + "/output/" ;

        this.BFO_htmlTree               = outputDir + "SO_upload_10_BFO_Tree.sql.txt" ;
        this.BFO_inputTree              = inputDir  + "BFOmapping/BFO_tree_struct.txt";
        this.BFOmapping                 = inputDir  + "BFO_ClassMapping.txt" ;
        this.BFOsubClasses              = outputDir + "SO_upload_05_BFO_subclasses.sql.txt" ;
        this.classAnnotations           = inputDir  + "OWLclassAnnotations.txt"  ; 
        this.classAnnotationsSQL        = outputDir + "SO_upload_07_class_annotations.sql.txt" ;
        this.classesSubclasses          = outputDir + "SO_upload_04_owl_classes.sql.txt" ;
        this.classStructure             = BFOmapping ;
        this.dataPropertyDefs           = inputDir  + "dataPropertyDefinitions.txt" ;
        this.dataPropertySQLdefs        =  outputDir + "SO_upload_16_dataProperties.sql.txt" ;
        this.dataPropertyTreeSQLdefs    = outputDir + "SO_upload_17_dataProp_Tree.sql.txt" ;
        this.disjointClasses            = outputDir + "SO_upload_06_disjoint_classes.sql.txt" ;
        this.header_SQL                 = outputDir + "SO_upload_01_XMLheader.sql.txt" ;
        this.header_txt                 = inputDir  + "ontologyHeader.txt" ;
        this.headerAnnotations_SQL      = outputDir + "SO_upload_02_headerAnnotations.sql.txt" ;
        this.headerAnnotations_txt      = inputDir  + "ontologyHeaderAnnotations.txt" ;
        this.HtmlHeaderCommandsIN_1_txt = inputDir  + "html/header_session_A.txt" ;
        this.HtmlHeaderCommandsIN_2_txt = inputDir  + "html/header_session_B.txt" ;
        this.HtmlHeaderCommandsOUT_SQL  = outputDir + "SO_upload_08_HTMLheader.sql.txt" ;
        this.HtmlTrailerCommandsIN_txt  = inputDir  + "html/trailer.txt" ;
        this.HtmlTrailerCommandsOUT_SQL = outputDir + "SO_upload_09_HTMLtrailer.sql.txt" ;
        this.inverseObjProperties       = outputDir + "SO_upload_13_invObjProp.sql.txt" ;
        this.n_ary_data_assertions_SQL  = outputDir + "SO_upload_20_n_ary_data_assertions_SQL.sql.txt" ;
        this.n_ary_participants_SQL     = outputDir + "SO_upload_19_n_ary_participants_SQL.sql.txt" ;
        this.n_ary_relations_SQL        = outputDir + "SO_upload_18_n_ary_relations_SQL.sql.txt" ;
        this.objPropertyAnnotations     = outputDir + "SO_upload_12_objPropAnn.sql.txt" ;
        this.objPropertyAttributes      = inputDir  + "objectPropertyAttributes.txt" ;
        this.objPropertyDefs            = inputDir  + "objectPropertyDefinitions.txt" ;
        this.objPropertyTree            = outputDir + "SO_upload_15_objProp_Tree.sql.txt" ;
        this.relationDefs_TXT           = inputDir  + "relationDefinitions.txt"  ;
        this.SKOSAnnotations_SQL        = outputDir + "SO_upload_03_skosAnnotations.sql.txt" ;
        this.SKOSAnnotations_txt        = inputDir  + "skosAnnotationProperties.txt" ;
        this.SO_htmlTree                = outputDir + "SO_upload_11_SO_Tree.sql.txt" ;
        this.SO_inputTree               = BFOmapping ;
        this.superObjProperties         = outputDir + "SO_upload_14_superObjProp.sql.txt" ;
        this.trailer_SQL                = outputDir + "SO_upload_99_XMLtrailer.sql.txt" ;
        this.trailer_txt                = inputDir  + "ontologyTrailer.txt" ;

    }   //  end of method resetFilenames()
    
}   //  end of class OWLpreprocessing
