package dataProfileWebSite;

import java.io.File;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import dataWarehousingTools.LogFile;
import dataWarehousingTools.Configuration;
import dataWarehousingTools.DashboardFile;


public class ColumnProfile 
{
    public ColumnProfile
    (
    	Configuration configuration, 
    	Connection connection, 
    	LogFile logFile, 
    	int databaseLinkId,
    	int tableProfileId, 
    	String databaseName,
    	String schemaName,
    	String tableName,
    	int rowCount,
    	Timestamp dateTimeStatisticsCollected
    )
    {
    	Statement statement = null;
    	ResultSet resultSet = null;
    	
		int columnProfileId;
		
		String columnName;
		String dataType;
		int dataLength;
		int nullCount;
		double percentPopulated;
		int distinctValueCount;
		long minInteger;
		BigDecimal minDecimal;		
		Timestamp minDate;
//		String minString;
		long maxInteger;
		BigDecimal maxDecimal;		
		Timestamp maxDate;
//		String maxString;
		boolean nullable;
		int maxLength;
		String tableProfileFileName;
		File checkExists;
		DashboardFile tableProfileFile;
		XmlElement xmlElement;
		Calendar today;
		DateFormat longDateFormat;
		DateFormat shortDateFormat;
		DecimalFormat integerFormat;
		DecimalFormat decimalFormat;
		DecimalFormat percentageFormat;
		String minDisplayValue;
		String minDisplayLong;
		String maxDisplayValue;
		String maxDisplayLong;


    	today = Calendar.getInstance();
    	longDateFormat = new SimpleDateFormat("EEE dd-MMM-yyyy HH:mm:ss");
        longDateFormat.format(today.getTime());
        shortDateFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
        shortDateFormat.format(today.getTime());
		integerFormat = new DecimalFormat("###,###,###,###,###");
		decimalFormat = new DecimalFormat("###,###,###,###.####");
		percentageFormat = new DecimalFormat("##0.00");
		
		minDisplayValue = new String("");
		maxDisplayValue = new String("");
		
		tableProfileFileName = new String(configuration.getHtmlFileLocation() + "TableProfile" + tableProfileId + ".htm");
		checkExists = new File(tableProfileFileName);
		if (checkExists.exists())
			return;
		
		tableProfileFile = new DashboardFile
		(
			configuration.getHtmlFileLocation() +
			"TableProfile" + tableProfileId + ".htm"
		);
		tableProfileFile.PutLine("<!DOCTYPE html>");
		tableProfileFile.PutLine("  <head>");
		tableProfileFile.PutLine("    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>");  
		tableProfileFile.PutLine
	    (
	    	"    <link rel=\"stylesheet\" type=\"text/css\" href=\"" +
	    	configuration.getLinkToStylesheets() +
	    	"style.css\"/>"
	    );
	    tableProfileFile.PutLine("  </head>");
	    tableProfileFile.PutLine("  <body>");

	    tableProfileFile.PutLine("    <table>");
	    tableProfileFile.PutLine("      <tr>");
	    tableProfileFile.PutLine("      <tr>");
	    tableProfileFile.PutLine("        <th>Database</th>");
	    tableProfileFile.PutLine("        <th>Schema</th>");
	    tableProfileFile.PutLine("        <th>Table</th>");
	    tableProfileFile.PutLine("        <th>Row Count</th>");
	    tableProfileFile.PutLine("        <th>Date Statistics Collected</th>");
	    tableProfileFile.PutLine("      </tr>");
	    tableProfileFile.PutLine("      <tr>");
	    tableProfileFile.PutLine("        <td>" + databaseName + "</td>");
	    tableProfileFile.PutLine("        <td>" + schemaName + "</td>");
	    tableProfileFile.PutLine("        <td>" + tableName + "</td>");
	    tableProfileFile.PutLine("        <td>" + integerFormat.format(rowCount) + "</td>");
	    tableProfileFile.PutLine("        <td>" + longDateFormat.format(dateTimeStatisticsCollected.getTime()) + "</td>");
	    tableProfileFile.PutLine("      </tr>");
	    tableProfileFile.PutLine("    </table>");

	    xmlElement = new XmlElement
	    (
	    	6, 
	    	"a", 
	    	"href=\"" +
	    	"index.html\"",
	    	"Back to List of Databases"
	    );
	    tableProfileFile.PutLine("<p>" + xmlElement.getXmlElement() + "</p>");

	    xmlElement = new XmlElement
	    (
	    	6, 
	    	"a", 
	    	"href=\"" +
	    	"Schema" + databaseLinkId + ".htm\"",
	    	"Back to List of Tables"
	    );
	    tableProfileFile.PutLine("<p>" + xmlElement.getXmlElement() + "</p>");
		
	    xmlElement = new XmlElement(2, "title", "", "Column Profiles for Table: " + tableName);
	    tableProfileFile.PutLine(xmlElement.getXmlElement());

	    xmlElement = new XmlElement(4, "h4", "", "Published: " + longDateFormat.format(today.getTime()) + " GMT");
	    tableProfileFile.PutLine(xmlElement.getXmlElement());
				
	    tableProfileFile.PutLine("    <div class=\"scrollable_table\">");
	    tableProfileFile.PutLine("      <table>");
	    tableProfileFile.PutLine("      <col width=\"9%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("      <col width=\"9%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("      <col width=\"9%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("      <col width=\"7%\">");
	    tableProfileFile.PutLine("        <thead>");
	    tableProfileFile.PutLine("          <tr>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Column Name</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Data Type</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:right;font-size:80%;\">Defined Length</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:center;font-size:80%;\">Nulls Allowed</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:right;font-size:80%;\">Null Count</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:right;font-size:80%;\">Percentage Populated</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:right;font-size:80%;\">Distinct Value Count</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Minimum Value</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Maximum Value</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:right;font-size:80%;\">Max Actual Length</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Link to Frequencies</th>");
	    tableProfileFile.PutLine("            <th style=\"text-align:left;font-size:80%;\">Link to Patterns</th>");
	    tableProfileFile.PutLine("          </tr>");
	    tableProfileFile.PutLine("        </thead>");
	    tableProfileFile.PutLine("        <tbody>");
    		
		try
		{
			statement = connection.createStatement();
		}
		catch(SQLException sqle)
		{
			logFile.logMessage(sqle.toString());
		}

		try
		{
			resultSet = statement.executeQuery
			(
				"select " +   	
					"id                             as column_profile_id, " +
					"table_profile_id, " + 
					"date_time_statistics_collected, " +
					"column_name, " +
					"data_type, " +
					"data_length, " +
					"null_count, " +
					"unique_value_count             as distinct_value_count, " +
					"min_number, " +
					"min_date, " +
					"min_string, " +
					"max_number, " +
					"max_date, " +
					"max_string, " +
					"nullable, " +
					"max_length " +
				"from " +
                    "column_profile " +
				"where " +
                    "table_profile_id = " + tableProfileId +
                "order by " +
                    "column_name"
            );
		}
		catch(SQLException sqle)
		{
			logFile.logMessage(sqle.toString());
		}
		
		try 
		{
			while (resultSet.next())
			{
				columnProfileId = resultSet.getInt("column_profile_id");
				dateTimeStatisticsCollected = resultSet.getTimestamp("date_time_statistics_collected");
				columnName = new String(resultSet.getString("column_name"));
				dataType = new String(resultSet.getString("data_type"));
				dataLength = resultSet.getInt("data_length");
				nullCount = resultSet.getInt("null_count");
				distinctValueCount = resultSet.getInt("distinct_value_count");

	            minDisplayValue = new String("");
	            minDisplayLong = new String("");
	            maxDisplayValue = new String("");
	            maxDisplayLong = new String("");
	            
	            if 
	            (
	            	dataType.equalsIgnoreCase("varchar") || 
	            	dataType.equalsIgnoreCase("nvarchar") || 
	            	dataType.equalsIgnoreCase("text") || 
	            	dataType.equalsIgnoreCase("char") ||
	            	dataType.equalsIgnoreCase("nchar")
	            )
	            {
	            	try
	            	{
	            	    minDisplayValue = new String(resultSet.getString("min_string"));
	            	}
	            	catch (NullPointerException npe)
	            	{
	            		minDisplayValue = new String("Missing");
	            	}
	            	if (resultSet.wasNull())
	            	{
	            		minDisplayValue = new String("Null");
	            	}
	            	if (minDisplayValue.length() > 24)
	            	{
		            	minDisplayLong = new String(minDisplayValue);
		            	minDisplayValue = new String(minDisplayLong.substring(0, 24) + "…");
	            	}
	            }
	            else if 
	            (
	            	dataType.equalsIgnoreCase("int4") || 
	            	dataType.equalsIgnoreCase("int2") || 
	            	dataType.equalsIgnoreCase("integer") ||
	            	dataType.equalsIgnoreCase("bigint") ||
	            	dataType.equalsIgnoreCase("smallint") ||
	            	dataType.equalsIgnoreCase("tinyint")
	            )
	            {
	            	minInteger = resultSet.getLong("min_number");
	            	if (resultSet.wasNull())
	            	{
	            		minDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		minDisplayValue = new String(integerFormat.format(minInteger));
	            	}
	            }
	            else if 
	            (
	            	dataType.equalsIgnoreCase("decimal") || 
	            	dataType.equalsIgnoreCase("numeric") ||
	            	dataType.equalsIgnoreCase("float") ||
	            	dataType.equalsIgnoreCase("double")
	            )
	            {
	            	minDecimal = resultSet.getBigDecimal("min_number");
	            	if (resultSet.wasNull())
	            	{
	            		minDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		minDisplayValue = new String(decimalFormat.format(minDecimal));
	            	}
	            }
	            else if (dataType.equalsIgnoreCase("date") || dataType.equalsIgnoreCase("timestamp"))
	            {
	            	minDate = resultSet.getTimestamp("min_date");
	            	if (resultSet.wasNull())
	            	{
	            		minDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		minDisplayValue = new String(shortDateFormat.format(minDate));
	            	}
	            }
	            else if (dataType.equals("bool"))
	            {
	            	minDisplayValue = new String("N/A");
	            }
	            	            
	            if 
	            (
	            	dataType.equalsIgnoreCase("varchar") || 
	            	dataType.equalsIgnoreCase("nvarchar") || 
	            	dataType.equalsIgnoreCase("text") || 
	            	dataType.equalsIgnoreCase("char") ||
	            	dataType.equalsIgnoreCase("nchar")
	            )
	            {
	            	try
	            	{
	            	    maxDisplayValue = new String(resultSet.getString("max_string"));
	            	}
	            	catch (NullPointerException npe)
	            	{
	            		maxDisplayValue = new String("Missing");
	            	}
	            	if (resultSet.wasNull())
	            	{
	            		maxDisplayValue = new String("Null");
	            	}
	            	if (maxDisplayValue.length() > 24)
	            	{
		            	maxDisplayLong = new String(maxDisplayValue);
		            	maxDisplayValue = new String(maxDisplayLong.substring(0, 24) + "…");
	            	}
	            }
	            else if 
	            (
	            	dataType.equalsIgnoreCase("int4") || 
	            	dataType.equalsIgnoreCase("int2") || 
	            	dataType.equalsIgnoreCase("integer") ||
	            	dataType.equalsIgnoreCase("bigint") ||
	            	dataType.equalsIgnoreCase("smallint") ||
	            	dataType.equalsIgnoreCase("tinyint")
	            )
	            {
	            	maxInteger = resultSet.getLong("max_number");
	            	if (resultSet.wasNull())
	            	{
	            		maxDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		maxDisplayValue = new String(integerFormat.format(maxInteger));
	            	}
	            }
	            else if 
	            (
	            	dataType.equalsIgnoreCase("decimal") || 
	            	dataType.equalsIgnoreCase("numeric") ||
	            	dataType.equalsIgnoreCase("float") ||
	            	dataType.equalsIgnoreCase("double")
	            )
	            {
	            	maxDecimal = resultSet.getBigDecimal("max_number");
	            	if (resultSet.wasNull())
	            	{
	            		maxDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		maxDisplayValue = new String(decimalFormat.format(maxDecimal));
	            	}
	            }
	            else if (dataType.equalsIgnoreCase("date") || dataType.equalsIgnoreCase("timestamp"))
	            {
	            	maxDate = resultSet.getTimestamp("max_date");
	            	if (resultSet.wasNull())
	            	{
	            		maxDisplayValue = new String("Null");
	            	}
	            	else
	            	{
	            		maxDisplayValue = new String(shortDateFormat.format(maxDate));
	            	}
	            }
	            else if (dataType.equals("bool"))
	            {
	            	maxDisplayValue = new String("N/A");
	            }

				nullable = resultSet.getBoolean("nullable");
				maxLength = resultSet.getInt("max_length");

				if (rowCount > 0)
				    percentPopulated = (double)(rowCount - nullCount) * 100 / rowCount;
				else
					percentPopulated = 0.00;
				
			    tableProfileFile.PutLine("        <tr>");
			    tableProfileFile.PutLine("          <td style=\"text-align:left;font-size:80%;\">" + columnName + "</td> ");
			    tableProfileFile.PutLine("          <td style=\"text-align:left;font-size:80%;\">" + dataType.toLowerCase() + "</td>");
			    tableProfileFile.PutLine("          <td style=\"text-align:right;font-size:80%;\">" + integerFormat.format(dataLength) + "</td>");
			    if (nullable)
			    {
			        tableProfileFile.PutLine("          <td style=\"text-align:center;font-size:80%;\">Yes</td>");
			    }
			    else
			    {
			    	tableProfileFile.PutLine("          <td style=\"text-align:center;font-size:80%;\">No</td>");
			    }
			    tableProfileFile.PutLine("          <td style=\"text-align:right;font-size:80%;\">" + integerFormat.format(nullCount) + "</td>");
			    
			    tableProfileFile.PutLine("          <td style=\"text-align:right;font-size:80%;\">" + percentageFormat.format(percentPopulated) + "%</td>");
			    
			    tableProfileFile.PutLine("          <td style=\"text-align:right;font-size:80%;\">" + integerFormat.format(distinctValueCount) + "</td>");

//			    check for PANs and mask			    
//			    tableProfileFile.PutLine("        <td style=\"text-align:left;font-size:80%;\">" + maskIfPan.mask(minDisplayValue) + "</td>");
//			    tableProfileFile.PutLine("        <td style=\"text-align:left;font-size:80%;\">" + maskIfPan.mask(maxDisplayValue) + "</td>");
			    
			    tableProfileFile.PutLine("          <td style=\"text-align:left;font-size:80%;\">" + minDisplayValue + "</td>");
			    tableProfileFile.PutLine("          <td style=\"text-align:left;font-size:80%;\">" + maxDisplayValue + "</td>");

			    
	            if
                (
	            	dataType.equalsIgnoreCase("varchar") || 
	            	dataType.equalsIgnoreCase("nvarchar") || 
	            	dataType.equalsIgnoreCase("text") || 
	            	dataType.equalsIgnoreCase("char") ||
	            	dataType.equalsIgnoreCase("nchar")
	            )
			    	tableProfileFile.PutLine("          <td style=\"text-align:right;font-size:80%;\">" + integerFormat.format(maxLength) + "</td>");
	            else
	            	tableProfileFile.PutLine("          <td style=\"text-align:right;color:DarkGray;font-size:70%;\">Not a string</td>");

//			    if (distinctValueCount == 1)
//			    {
//			    	tableProfileFile.PutLine("        <td style=\"text-align:left;color:DarkGray;font-size:70%;\">All values the same</td>");
//			    }
//			    else if (distinctValueCount == rowCount)
//			    {
//			    	tableProfileFile.PutLine("        <td style=\"text-align:left;color:DarkGray;font-size:70%;\">Every value distinct</td>");
//			    }
//			    else
//			    {
				    xmlElement = new XmlElement
				    (
				    	6, 
				    	"a", 
				    	"href=\"" +
				    	"Frequency" +
				    	columnProfileId +
				    	".htm\"",
				    	"Frequency"
				    );
		            tableProfileFile.PutLine
				    (
				    	"        <td style=\"text-align:left;font-size:80%;\">" +	
				    	xmlElement.getXmlElement() + 
				    	"</td>"
				    );
				    
				    new Frequencies
				    (
				    	configuration, 
				    	connection, 
				    	logFile, 
				    	databaseLinkId,
				    	databaseName,
				    	schemaName,
				    	tableName, 
				    	rowCount, 
				    	distinctValueCount,
				    	tableProfileId,
				    	columnProfileId, 
				    	columnName, 
				    	dateTimeStatisticsCollected
				    );
//			    }
			    
	            if 
	            (
	            	dataType.equalsIgnoreCase("varchar") || 
	            	dataType.equalsIgnoreCase("nvarchar") || 
	            	dataType.equalsIgnoreCase("text") || 
	            	dataType.equalsIgnoreCase("char") ||
	            	dataType.equalsIgnoreCase("nchar")
	            )
	            {
			        xmlElement = new XmlElement
				    (
				    	6, 
				    	"a", 
				    	"href=\"" +
				    	"Pattern" +
				    	columnProfileId +
				    	".htm\"",
				    	"Pattern"
				    );
		            tableProfileFile.PutLine
				    (
				    	"        <td style=\"text-align:left;font-size:80%;\">" +	
				    	xmlElement.getXmlElement() + 
				    	"</td>"
				    );
				    
				    tableProfileFile.PutLine("      </tr>");
				    
				    new Patterns
				    (
				    	configuration, 
				    	connection, 
				    	logFile, 
				    	databaseLinkId,
				    	databaseName,
				    	schemaName,
				    	tableName, 
				    	rowCount, 
				    	tableProfileId,
				    	columnProfileId, 
				    	columnName, 
				    	dateTimeStatisticsCollected
				    );
	            }
	            else
	            {
			    	tableProfileFile.PutLine("        <td style=\"text-align:left;color:DarkGray;font-size:70%;\">Not a string</td>");	            	
	            }
			}
		} 
		catch (SQLException sqle) 
		{
			logFile.logMessage(sqle.toString());
		}
		
		tableProfileFile.PutLine("        </tbody>");
		tableProfileFile.PutLine("      </table>");
		tableProfileFile.PutLine("    </div>");
		
	    xmlElement = new XmlElement(4, "h4", "", "Published: " + longDateFormat.format(today.getTime()) + " GMT");
	    tableProfileFile.PutLine(xmlElement.getXmlElement());

	    tableProfileFile.PutLine("  </body>");
		
		tableProfileFile.Close();
    }
}
