/**
 * 
 */
package cz.hsrs.rest.util;

import java.sql.ResultSet;
import java.sql.SQLException;

import cz.hsrs.db.pool.SQLExecutor;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * @author mkepka
 *
 */
public class TrackRestUtil {

	/**
	 * Function selects days of stored positions for given list of units
	 * @param unitIds - list of unit IDs separated by commas
	 * @return JSON Array as String containing arrays of active days for each unit in group
	 * @throws SQLException 
	 */
	public static String getDatesByUnits(String unitIds) throws SQLException {
		String query = "SELECT t.unit_id, t.description, json_agg(t.date_trunc) FROM"
				+ " (SELECT u.unit_id, u.description, date_trunc('day', up.time_stamp)::date"
					+ " FROM public.units_positions up, units u"
					+ " WHERE u.unit_id IN ("+unitIds+") AND u.unit_id = up.unit_id"
					+ " GROUP BY u.unit_id, date_trunc ORDER BY u.unit_id, date_trunc) t"
				+ " GROUP BY t.unit_id, t.description;";
		ResultSet res = SQLExecutor.getInstance().executeQuery(query);
		JSONArray units = new JSONArray();
		if(res != null) {
			while(res.next()) {
				JSONObject unit = new JSONObject();
				unit.element("unit_id", res.getLong("unit_id"));
				unit.element("unit_description", res.getString("description"));
				unit.element("dates", res.getString("json_agg"));
				units.add(unit);
			}
		}
		return units.toString();
	}

	/**
	 * Function selects days of stored positions for units in given group 
	 * @param groupId - ID of group for selecting list of units
	 * @return JSON Array as String containing arrays of active days for each unit in group
	 * @throws SQLException
	 */
	public static String getDatesByUnitsByGroup(int groupId) throws SQLException {
		String query = "SELECT t.unit_id, t.description, json_agg(t.date_trunc) FROM"
				+ " (SELECT u.unit_id, u.description, date_trunc('day', up.time_stamp)::date"
				+ " FROM public.units_positions up, units u"
				+ " WHERE u.unit_id IN ("
				+ "SELECT unit_id FROM units_to_groups WHERE group_id = "+groupId+")"
				+ " GROUP BY u.unit_id, date_trunc ORDER BY u.unit_id, date_trunc) t"
				+ " GROUP BY t.unit_id, t.description;";
		ResultSet res = SQLExecutor.getInstance().executeQuery(query);
		JSONArray units = new JSONArray();
		if(res != null) {
			while(res.next()) {
				JSONObject unit = new JSONObject();
				unit.element("unit_id", res.getLong("unit_id"));
				unit.element("unit_description", res.getString("description"));
				unit.element("dates", res.getString("json_agg"));
				units.add(unit);
			}
		}
		return units.toString();
	}
	
	/**
	 * Function selects days of stored positions for units in given group
	 * @param groupName - name of unit group
	 * @return JSON Array as String containing arrays of active days for each unit in group
	 * @throws SQLException
	 */
	public static String getDatesByUnitsByGroup(String groupName) throws SQLException {
		String query = "SELECT t.unit_id, t.description, json_agg(t.date_trunc) FROM"
				+ " (SELECT u.unit_id, u.description, date_trunc('day', up.time_stamp)::date"
				+ " FROM public.units_positions up, units u"
				+ " WHERE u.unit_id IN ("
				+ "SELECT unit_id FROM units_to_groups utg, groups g WHERE utg.group_id = g.id AND g.group_name='"+groupName+"')"
				+ " GROUP BY u.unit_id, date_trunc ORDER BY u.unit_id, date_trunc) t"
				+ " GROUP BY t.unit_id, t.description;";
		ResultSet res = SQLExecutor.getInstance().executeQuery(query);
		JSONArray units = new JSONArray();
		if(res != null) {
			while(res.next()) {
				JSONObject unit = new JSONObject();
				unit.element("unit_id", res.getLong("unit_id"));
				unit.element("unit_description", res.getString("description"));
				unit.element("dates", res.getString("json_agg"));
				units.add(unit);
			}
		}
		return units.toString();
	}

	/**
	 * 
	 * @param unitId
	 * @param sensorIds
	 * @param fromDate
	 * @param toDate
	 * @return
	 * @throws SQLException
	 */
	public static String getTrackPoints(long unitId, String sensorIds, String fromDate, String toDate) throws SQLException {
		StringBuilder query = new StringBuilder();
		query.append("SELECT t.gid, t.geom, t.time_stamp, json_agg(json_build_object(t.sensor_name::text, t.observed_value))"
					+ " FROM ("
						+ "SELECT up.gid, st_asgeojson(up.the_geom) AS geom, up.time_stamp, o.observed_value, s.sensor_name"
						+ " FROM units_positions up, observations o, sensors s");
		query.append(" WHERE up.unit_id = "+unitId);
		if(sensorIds != null) {
			query.append(" AND o.sensor_id IN ("+sensorIds+")");
		}
		query.append(" AND up.gid = o.gid AND o.sensor_id = s.sensor_id");
		if(fromDate != null && toDate == null) { 
			query.append(" AND up.time_stamp >= '"+fromDate+"' AND up.time_stamp < ('"+fromDate+"'::date + interval '1 day')");
		}
		if(fromDate != null && toDate != null) {
			query.append(" AND up.time_stamp >= '"+fromDate+"' AND up.time_stamp < '"+toDate+"'");
		}
		query.append(" ORDER BY up.time_stamp) t GROUP BY t.gid, t.geom, t.time_stamp;");
		
		String queryFull = query.toString();
	
		ResultSet res = SQLExecutor.getInstance().executeQuery(queryFull);
		
    	JSONObject geojson = new JSONObject();
    	if(res != null) {
    		geojson.element("type", "FeatureCollection");
        	JSONArray features = new JSONArray();
        	
        	while (res.next()) {
        		JSONObject feature = new JSONObject();
            	feature.element("type", "Feature");
            	
            	JSONObject properties = new JSONObject();
            	properties.element("time_stamp", res.getString("time_stamp")+"00");
            	JSONObject obs = JSONObject.fromObject(res.getObject("json_agg"));
            	JSONArray arr = JSONArray.fromObject(obs.get("value"));
            	for(int i = 0; i < arr.size(); i++) {
            		properties.accumulateAll(arr.getJSONObject(i));
            	}
            	feature.element("properties", properties);
            	feature.element("geometry", res.getString("geom"));
            	
            	features.add(feature);
        	}        	
        	geojson.element("features", features);
    	}
    	return geojson.toString(); 
	}
}
