package cz.hsrs.servlet.provider;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;

import javax.naming.AuthenticationException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.HttpHeaders;

import cz.hsrs.db.DBJsonUtils;
import cz.hsrs.db.util.UtilFactory;
import cz.hsrs.servlet.feeder.ServiceParameters;
import cz.hsrs.servlet.security.LoginUser;

/**
 * Servlet provides methods for Sensor services 
 * @author jezekjan
 *
 */
public class SensorService extends DBServlet {

    private static final long serialVersionUID = 1L;

    public static final String GET_SENSORS = "GetSensors";
    public static final String GET_ALL_SENSORS = "GetAllSensors";
    public static final String GET_ALL_SENSOR_TYPES = "GetAllSensorTypes";
    public static final String GET_ALL_PHENOMENONS = "GetAllPhenomenons";
    public static final String GET_OBSERVATIONS = "GetObservations";
    public static final String GET_LAST_OBSERVATIONS = "GetLastObservations";

    private UtilFactory db;

    public void init() throws ServletException {
        super.init();
        
        try {
            db = new UtilFactory();
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        super.doGet(request, response);
        RequestParameters params = new RequestParameters(request);
        
        /* session login method */
        LoginUser loggedUser;
        try {
            loggedUser = getAuthenticatedLoginUser(request);
            String userName = loggedUser.getUserName();
            params.setUser(userName);
        } catch (AuthenticationException e1) {
            throw new ServletException("Authentication failure for request "+ request.getQueryString());
        }
        
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");

        /*
         * /SensorService?Operation=GetSensors&user=meteor&unit_id=104200002
         * /SensorService?Operation=GetObservations&user=meteor&unit_id=104200002&sensor_id=&fromTime=2016-02-01&toTime=2016-02-04&trunc=day
         * /SensorService?Operation=GetObservations&user=meteor&unit_id=104200002&sensor_id=&fromTime=2016-02-01&toTime=2016-02-04
         * /SensorService?Operation=GetLastObservations&user=meteor&unit_id=104200002&sensor_id=690020001
         * /SensorService?Operation=GetLastObservations&user=meteor&unit_id=104200002
         * /SensorService?Operation=GetLastObservations&user=meteor&group=meteo2
         * /SensorService?Operation=GetLastObservations&user=meteor&group=meteo2&sensor_id=690020001
         * /SensorService?Operation=GetAllPhenomenons
         * /SensorService?Operation=GetAllSensors
         * /SensorService?Operation=GetAllSensorTypes
         */
        PrintWriter out = response.getWriter();
        try {
            /* GetSensors */
            if (request.getParameter(ServiceParameters.OPERATION).equals(GET_SENSORS)) {
                boolean isAffiliated = db.analystUtil.checkUnitAffiliation2User(params.getUser(), params.getUnitId());
                if(isAffiliated){
                    DBJsonUtils.writeJSON(out, db.sensorUtil.getUnitsSensors(params.getUnitId()));
                } else{
                    throw new SQLException("Specified unit does not exist in any group of given user!");
                }
                /* Get All Sensors */
            } else if (request.getParameter(ServiceParameters.OPERATION).equalsIgnoreCase(GET_ALL_SENSORS)) {
            	DBJsonUtils.writeJSON(out,db.sensorUtil.getSensors());
            /* GET All Sensor Types */
            } else if (request.getParameter(ServiceParameters.OPERATION).equalsIgnoreCase(GET_ALL_SENSOR_TYPES)) {
            	DBJsonUtils.writeJSON(out,db.sensorUtil.getSensorTypes());
            	/* GetAllPhenomenons */
            } else if (request.getParameter(ServiceParameters.OPERATION).equalsIgnoreCase(GET_ALL_PHENOMENONS)) {
            	DBJsonUtils.writeJSON(out,db.sensorUtil.getPhenomenons());
            /* GetObservations */
            } else if (request.getParameter(ServiceParameters.OPERATION).equals(GET_OBSERVATIONS)) {
                boolean isAffiliated = db.analystUtil.checkUnitAffiliation2User(params.getUser(), params.getUnitId());
                if(isAffiliated){
                    /* Pokud je dan trunc */
                    if (params.trunc != null) {
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getSensorObservationsTrunc(
                                params.getUnitId(), params.getSensorId(), params.from, params.to, params.trunc));
                    } else {
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getSensorObservations(
                                params.getUnitId(), params.getSensorId(), params.from, params.to));
                    }
                } else{
                    throw new SQLException("Specified unit does not exist in any group of given user!");
                }
            /* GetLastObservations */
            } else if(request.getParameter(ServiceParameters.OPERATION).equals(GET_LAST_OBSERVATIONS)){
                if(params.getGroup() == null && params.getUnitId() != 0 && params.getSensorId() != 0){
                    boolean isAffiliated = db.analystUtil.checkUnitAffiliation2User(params.getUser(), params.getUnitId());
                    if(isAffiliated){
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getSensorLastObservation(params.getUnitId(), params.getSensorId()));
                    } else{
                        throw new SQLException("Specified unit does not exist in any group of given user!");
                    }
                } else if(params.getGroup() == null && params.getUnitId() != 0 && params.getSensorId() == 0){
                    boolean isAffiliated = db.analystUtil.checkUnitAffiliation2User(params.getUser(), params.getUnitId());
                    if(isAffiliated){
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getUnitSensorsLastObservations(params.getUnitId()));
                    } else{
                        throw new SQLException("Specified unit does not exist in any group of given user!");
                    }
                } else if(params.getGroup() != null && params.getUnitId() == 0 && params.getSensorId() == 0){
                    boolean isAffiliated = db.groupUtil.checkGroupAffiliation2User(params.getUser(), params.getGroup());
                    if(isAffiliated){
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getUnitsSensorsLastObservations(params.getGroup()));
                    } else{
                        throw new SQLException("Specified unit does not exist in any group of given user!");
                    }
                } else if(params.getGroup() != null && params.getUnitId() == 0 && params.getSensorId() != 0){
                    boolean isAffiliated = db.groupUtil.checkGroupAffiliation2User(params.getUser(), params.getGroup());
                    if(isAffiliated){
                        DBJsonUtils.writeJSON(out, db.sensorUtil.getUnitsSensorsLastObservations(params.getGroup(), params.getSensorId()));
                    } else{
                        throw new SQLException("Specified unit does not exist in any group of given user!");
                    }
                } else{
                    throw new ServletException("Wrong combination of parameters "+ request.getQueryString());
                }
            } else {
                throw new ServletException("Wrong request "+ request.getQueryString());
            }
        } catch (SQLException e) {
            super.solveGetException(e, out);
        }
    }

    static class RequestParameters {
        private String user;
        private final String group;
        private final long unitId;
        private final long sensorId;
        private final String from;
        private final String to;
        private final String trunc;

        RequestParameters(HttpServletRequest request) throws NullPointerException {
            Object uid = request.getParameter("unit_id");
            this.unitId = uid != null ? Long.parseLong(uid.toString()) : 0;

            Object sid = request.getParameter("sensor_id");
            this.sensorId = sid != null ? Long.parseLong(sid.toString()) : 0;

            Object tr = request.getParameter("trunc");
            this.trunc = tr != null ? tr.toString() : null;

            Object fro =  request.getParameter("from");
            this.from = fro != null ? fro.toString() : "1900-01-01 00:00:00+01";

            Object too =  request.getParameter("to");
            this.to = too != null ? too.toString() : "3000-01-01 00:00:00+01";

            Object userO = request.getParameter("user");
            this.user = userO != null ? userO.toString() : null;

            Object groupO = request.getParameter("group");
            this.group = groupO != null ? groupO.toString() : null;
        }

        public long getUnitId() {
            return unitId;
        }
        public long getSensorId() {
            return sensorId;
        }
        public String getFromTime() {
            return from;
        }
        public String getToTime() {
            return to;
        }
        public String getTrunc() {
            return trunc;
        }
        public String getUser() {
            return user;
        }
        public void setUser(String user) {
            this.user = user;
        }
        public String getGroup() {
            return group;
        }
    }
}