package cz.hsrs.db.util;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;

import cz.hsrs.db.model.Unit;
import cz.hsrs.db.pool.SQLExecutor;

/**
 * 
 * @author mkepka
 *
 */
public class ExportUtil {
    
    /**
     * Export method for crosstab style 
     * e.g.: time_stamp;unit1;unit2;...;unitN
     * @param sensorId
     * @param groupId
     * @param fromTime
     * @param toTime
     * @return
     * @throws SQLException
     */
    public static String getObservationsBySensorByGroupCross(long sensorId, int groupId, String fromTime, String toTime, boolean nullable) throws SQLException {
        List<Unit> unitList = UnitUtil.getUnitsBySensorIdByGroup(sensorId, groupId);
        String CSV = "";
        // there are some units to export
        if(!unitList.isEmpty()) {
            // define Query
            StringBuilder selectString = new StringBuilder();
            StringBuilder unitString = new StringBuilder();
            selectString.append("SELECT time_stamp\n");
            unitString.append("AS ct( \"time_stamp\" text\n");
            for (int i = 0; i <unitList.size(); i++) {
                Unit unit = unitList.get(i);
                if(nullable == true) {
                	selectString.append(", \""+unit.getUnitId()+"\"");
                }
                else {
                	selectString.append(", COALESCE(\""+unit.getUnitId()+"\", 0) AS \""+unit.getUnitId()+"\"");
                }
                unitString.append(", \""+unit.getUnitId()+"\" double precision");
            }
            unitString.append(" ) ORDER BY time_stamp;");
            StringBuilder fromString = new StringBuilder();
            fromString.append(" FROM crosstab( $$\r\n" + 
                    " SELECT to_char(time_stamp, 'DD.MM.YYYY HH24:MI:SS'), unit_id, observed_value FROM observations\r\n" + 
                    " WHERE unit_id IN (SELECT unit_id FROM units_to_groups WHERE group_id = "+groupId+")\r\n" + 
                    " AND sensor_id = "+sensorId+"\r\n"); 
            if(fromTime != null) {
                fromString.append(" AND time_stamp >= '"+fromTime+"'\r\n");
            }
            if(toTime != null) {
                fromString.append(" AND time_stamp < '"+toTime+"'\r\n");
            }
            fromString.append(" ORDER BY time_stamp, unit_id\r\n$$) ");
            
            String query = selectString.toString() + fromString + unitString.toString();
            
            ResultSet res = SQLExecutor.getInstance().executeQuery(query);
            if(res != null) {
                CSV = CSVWriter(res);
            }
        }
        return CSV;
    }
    
    /**
     * 
     * @param res
     * @return
     */
    private static String CSVWriter(ResultSet res) {
        try {
            String CSV = null;
            ResultSetMetaData meta = res.getMetaData();
            // Head
            StringBuilder CSVhead = new StringBuilder();
            for (int i = 1; i <= meta.getColumnCount(); i++) {
                CSVhead.append("\"");
                CSVhead.append(meta.getColumnName(i));
                CSVhead.append("\"");
                if(i != meta.getColumnCount()) {
                    CSVhead.append(";");
                }
                else {
                    CSVhead.append("\r\n");
                }
            }
            // Data
            StringBuilder data = new StringBuilder();
            while(res.next()) {
                StringBuilder rowCSV = new StringBuilder();
                for (int i = 1; i <= meta.getColumnCount(); i++) {
                    int colType = meta.getColumnType(i);
                    if(colType == Types.DATE || colType == Types.VARCHAR || colType == Types.TIME || colType == Types.TIMESTAMP_WITH_TIMEZONE) {
                        rowCSV.append("\"");
                        rowCSV.append(res.getString(i));
                        rowCSV.append("\"");
                    }
                    else {
                    	double val = res.getDouble(i);
                    	if (res.wasNull()) {
                    		rowCSV.append("");
                    	}
                    	else {
                    		rowCSV.append(val);
                    	}
                    }
                    if(i != meta.getColumnCount()) {
                        rowCSV.append(";");
                    }
                    else {
                        rowCSV.append("\r\n");
                    }
                }
                data.append(rowCSV.toString());
            }
            CSV = CSVhead.toString() + data.toString();
            return CSV;
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}