package OWLpreprocessing;

import java.io.*;
import java.util.*;

public class OWL_CreaSOcollapsibleTree
{
    /**
	 *  Common file handling methods
     */
    private OWL_BufferedWriterUtils bwu        = new OWL_BufferedWriterUtils() ;
    private BufferedWriter      bw         = null ; 
	private int                 indentSize = 4; // Number of spaces per indentation level
    private int                 itemCount  = 0 ;
    
    OWL_CreaSOcollapsibleTree(String DBname,
		                      String inputFile,
			                  String outputFile
			                 )
    {
        List<String> lines = new ArrayList<>();
        
        try (BufferedReader br = new BufferedReader(new FileReader(inputFile))) 
        {
            String line;
            
            while ((line = br.readLine()) != null) 
            {
                if (!line.trim().isEmpty()) 
                {
                    int endOfClassNamePosition = line.indexOf(" ") ;
                    if (endOfClassNamePosition > 0)
                    {
                        line = line.substring(0, endOfClassNamePosition) ;
                    }

                    lines.add(line);
                }
                
                this.itemCount++ ;
            }
        }
        catch (IOException e)
        {
            e.printStackTrace() ;
        }
        
        try (BufferedWriter tmpBw = bwu.createBufferedWritablefile(outputFile))
        {
        	this.bw = tmpBw ;
        	
        	writeSQLheader(DBname, bw, outputFile) ;
        	
            Stack<Integer> levelStack = new Stack<>();
            
            int currentLevel = 0;

            for (int i = 0; i < lines.size(); i++) 
            {
                String line = lines.get(i);
                String text = line.trim();

                int level   = countLeadingSpaces(line) / indentSize;

                // Close tags if we're going up the tree
                while (currentLevel > level) 
                {
                    insertSQLrecord("</details>", "SO_TREE", "html_cmd") ;

                    currentLevel--;

                    if (!levelStack.isEmpty()) 
                    	levelStack.pop();
                }

                /* Open new details if we're going deeper
                 * 
                 */
                if (level > currentLevel) 
                {
                    insertSQLrecord("<details>", "SO_TREE", "html_cmd") ;

                	String record = "<summary>" + addURLto(escapeHtml(text)) +
                                    "</summary>";

                    insertSQLrecord(record, "SO_TREE", "html_cmd") ;
                	
                	levelStack.push(level);
                    currentLevel = level;
                } 
                else 
                {
                    // Same level or going up - close previous details and open new one
                    if (currentLevel > 0) 
                    {
                        insertSQLrecord("</details>", "SO_TREE", "html_cmd") ;
                    	
                        levelStack.pop();
                    }
                    
                    insertSQLrecord("<details>", "SO_TREE", "html_cmd") ;
                	
                    String record = "<summary>" + addURLto(escapeHtml(text)) +
                                    "</summary>";

                    insertSQLrecord(record, "SO_TREE", "html_cmd") ;

                    levelStack.push(level);

                    currentLevel = level;
                }
            }

            // Close any remaining open tags
            while (!levelStack.isEmpty()) 
            {
                insertSQLrecord("</details>", "SO_TREE", "html_cmd") ;

                levelStack.pop();
            }
            
            this.bw.write("\nCOMMIT ;\n");
        }
        catch (IOException e)
        {
            e.printStackTrace() ;
        }
        
        /**
         *  Logging of the result
         */
        bwu.log(new StringBuilder()
                    .append("    asserted " + this.itemCount + " item(s) to SO structure\n")
                    .toString()
               ) ;
    }

    private  int countLeadingSpaces(String s)
    {
        int count = 0;
        
        while (count < s.length() && s.charAt(count) == ' ')
        	count++;
        
        return count;
        
    }   //  end of method countLeadingSpaces()

    private String escapeHtml(String s) 
    {
        return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
        
    }   //  end of method escapeHtml()

    private String addURLto(String item)
    {
        if (item.compareTo("owl:Thing") == 0)
               return item ;

        item = item.substring(0, item.indexOf(' ')) ;
        
        return "<a href=\"#" + item + "\">" + item + "</a>" ;

    }   //  end of method addURLto()
    
    private void writeSQLheader(String         DBname,
    		                    BufferedWriter bw,
    		                    String         outputFile)
    {
        ArrayList<String> hdr = new ArrayList<>() ;
        
        hdr.add("/*") ; 
        hdr.add("    Title:       " + outputFile)  ;
        hdr.add("    Description: Generating SO tree html header in SQL format") ;
        hdr.add("    Format:      OWL/XML encoding") ;
        hdr.add("    Written by:  Java class " + this.getClass().getSimpleName()) ;
        hdr.add("    Date:        " + bwu.getCurrTime()) ;
        hdr.add(" */") ; 
        hdr.add("") ; 
        hdr.add("USE   " + DBname + " ;") ;
        hdr.add("") ; 
        hdr.add("SET   TRANSACTION READ WRITE ;") ;
        hdr.add("START TRANSACTION ;") ; 
        
        bwu.writeBufferedWritablefile(bw, hdr) ;

    }   //  end of writeSQLheader()

    private void insertSQLrecord(String         record, 
    		                     String         tableName, 
    		                     String         columnName) 
    {
    	String SQLinsertLine = String.format(
               "\nINSERT INTO " + tableName + " (" + columnName + ")\n" +
               "VALUES (" +
               "\'%s\'" + ") ;\n", record) ;
    	
        try { this.bw.write(SQLinsertLine); }
        catch (IOException e) { e.printStackTrace() ; }
    	
    }   //  end of method insertSQLrecord()

}   //end of class Create_SO_CollapsibleTree


