package OWL2generator;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.sql.Connection;

public class GenerateNewIndividualName
{
    private final int        leadingZeroesInIndividualNameSuffix = 6 ;  //  e.g. actor_ID000012
    private       Connection conn                                = null ;

    GenerateNewIndividualName(Connection conn) 
    { 
    	this.conn = conn ; 
    }

    public void __individualTest()
    {
        System.out.println("individual is >" + getNewIndividualName("Adoption") + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Adoption") + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Adoption") + "<") ;
       
        System.out.println("individual is >" + getNewIndividualName("Anomie")   + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Anomie")   + "<") ;
        
        System.out.println("individual is >" + getNewIndividualName("Collective_Causal_Event")   + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Collective_Causal_Event")   + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Collective_Causal_Event")   + "<") ;
        System.out.println("individual is >" + getNewIndividualName("Collective_Causal_Event")   + "<") ;
        
    }   //  end of method __individualTest()
    
    private String cvtThe1stCharToLowercase(String s) 
    {
        if (s == null || s.isEmpty()) 
            return s;
        
        int firstCodePoint = s.codePointAt(0);
        int lowerFirst     = Character.toLowerCase(firstCodePoint);
        int firstLen       = Character.charCount(firstCodePoint);
        
        if (firstCodePoint == lowerFirst) 
            return s;

        return new StringBuilder(s.length())
                                  .appendCodePoint(lowerFirst)
                                  .append(s.substring(firstLen))
                                  .toString();
        
    }   //  end of method cvtThe1stCharToLowercase ()
    
    private int getIncrementedIndividualCount(String classIri) 
    {
        int count = 0;
    
        // Session diagnostics
        try (java.sql.Statement s = this.conn.createStatement();
             java.sql.ResultSet rs = s.executeQuery(
                 "SELECT DATABASE(), @@autocommit, @@session.tx_read_only, @@transaction_isolation")) 
        { }
        catch (java.sql.SQLException ignore) {}
    
        // Read current count
        try (java.sql.PreparedStatement psSel = this.conn.prepareStatement(
                "SELECT class_individual_count FROM DBFOsociology.OWL_CLASSES WHERE class_IRI = ?")) 
        {
            psSel.setString(1, classIri);
            try (java.sql.ResultSet rs = psSel.executeQuery()) 
            {
                if (rs.next()) 
                {
                    count = rs.getInt(1);
                }
            }
        } 
        catch (java.sql.SQLException e) 
        {
            System.out.println("Cannot query the database");
            System.out.println("SQLException: " + e.getMessage());
            System.out.println("SQLState: " + e.getSQLState());
            System.out.println("VendorError: " + e.getErrorCode());
            e.printStackTrace();
            return count;
        }
        
        int newCount = count + 1;
        
        boolean originalAutoCommit = true;
        try 
        {
            originalAutoCommit = this.conn.getAutoCommit();
            this.conn.setAutoCommit(false);
    
            try (java.sql.PreparedStatement psUpd = this.conn.prepareStatement(
                    "UPDATE DBFOsociology.OWL_CLASSES SET class_individual_count = ? WHERE class_IRI = ?")) 
            {
                psUpd.setInt(1, newCount);
                psUpd.setString(2, classIri);
                psUpd.executeUpdate();
            }
    
            this.conn.commit();
        } 
        catch (java.sql.SQLException e) 
        {
            try { this.conn.rollback(); } catch (java.sql.SQLException ignore) 
            {}
            
            System.out.println("Cannot update the database");
            System.out.println("SQLException: " + e.getMessage());
            System.out.println("SQLState: " + e.getSQLState());
            System.out.println("VendorError: " + e.getErrorCode());
            e.printStackTrace();
        } 
        finally 
        {
            try 
            { this.conn.setAutoCommit(originalAutoCommit); } 
            catch (java.sql.SQLException ignore) 
            { }
        }
    
        // Verify after commit
        try (java.sql.PreparedStatement psVerify = this.conn.prepareStatement(
                "SELECT class_individual_count FROM DBFOsociology.OWL_CLASSES WHERE class_IRI = ?")) 
        {
            psVerify.setString(1, classIri);
            try (java.sql.ResultSet rsVerify = psVerify.executeQuery()) 
            { }
        } 
        catch (java.sql.SQLException e) 
        {
            System.out.println("Cannot verify the database value");
            System.out.println("SQLException: " + e.getMessage());
            System.out.println("SQLState: " + e.getSQLState());
            System.out.println("VendorError: " + e.getErrorCode());
            e.printStackTrace();
        }
    
        return newCount;
        
    }   //  end of method getIncrementedIndividualCount() 

    public String getNewIndividualName(String class_IRI)
    {
        int incremented_class_individual_count = getIncrementedIndividualCount(class_IRI) ;
        if (incremented_class_individual_count == -1)
        {
            System.err.println("Fatal error: DB could not be updated.") ;
            System.exit(-1) ;
        }
        
        String numberString = Integer.toString(incremented_class_individual_count);
        int    zerosToAdd   = this.leadingZeroesInIndividualNameSuffix - numberString.length();

        String zeros = Stream.generate(() -> "0").limit(zerosToAdd).collect(Collectors.joining());

    	return cvtThe1stCharToLowercase(class_IRI + "_ID" + zeros + numberString) ;
        
    }   //  end of method getNewIndividualName()

}   //  end of class GenerateNewIndividualName