/**
 * 
 */
package cz.hsrs.servlet.provider;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cz.hsrs.db.DBJsonUtils;
import cz.hsrs.db.model.NoItemFoundException;
import cz.hsrs.db.util.UtilFactory;
import cz.hsrs.servlet.feeder.ServiceParameters;

/**
 * Servlet providing FarmTelemetry analyses
 * @author mkepka
 *
 */
public class AnalystService extends DBServlet{

    private static final long serialVersionUID = 1L;
    private UtilFactory db;
    
    public static final String GET_WORK_ON_SITES = "GetWorkOnSites";
    public static final String GET_TRACTOR_UTILIZATION = "GetTractorUtilization";
    public static final String GET_TRACTOR_WORKDAY = "GetTractorWorkday";
    public static final String GET_FIELD_OVERVIEW = "GetActivitiesFieldOverview";
    public static final String GET_FIELD_OVERVIEW_POINT = "GetActivitiesFieldOverviewByPoint";
    public static final String GET_FIELD_OVERVIEW_PERIOD = "GetActivitiesFieldOverviewPeriod";
    public static final String GET_FIELD_OVERVIEW_FUEL = "GetFieldFuelSummary";
    public static final String GET_TRACTOR_ACTIVE_PERIOD = "GetTractorActivePeriod";
    public static final String GET_ACTIVE_TRACTORS_PERIOD = "GetActiveTractorsPeriod";
    public static final String GET_MANAGEMENT_ZONES_OVERVIEW = "GetManagementZonesOverview";
    public static final String GET_MANAGEMENT_ZONES_OVERVIEW_2 = "GetManagementZonesOverview2";
    public static final String GET_MANAGEMENT_ZONES_OVERVIEW_POINT = "GetManagementZonesOverviewByPoint";
    public static final String GET_MANAGEMENT_ZONES_OVERVIEW_POINT_2 = "GetManagementZonesOverviewByPoint2";
    public static final String GET_DAILY_FIELD_ACTIVITIES = "GetDailyFieldActivities";
    public static final String GET_DAILY_FIELD_ACTIVITIES_POINT = "GetDailyFieldActivitiesByPoint";
    public static final String GET_PLOTS_GEOM = "GetPlotsGeom";
    public static final String GET_MAN_ZONES_GEOM = "GetManagementZonesGeom";
    public static final String GET_MAN_ZONE_GEOM = "GetManagementZoneGeom";
    public static final String GET_MAN_ZONE_GEOM_POINT = "GetManagementZoneGeomByPoint";
    
    public AnalystService(){
        super();
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        super.doGet(request, response);
        
        /* 
         * AnalystService?Operation=GetWorkOnSites&user=telemetry&unit_id=356173060289134&date=2015-11-13
         * AnalystService?Operation=GetWorkOnSites&user=telemetry&unit_id=356173060289134&from=2015-11-13&to=2015-11-15
         * 
         * AnalystService?Operation=GetTractorUtilization&user=telemetry&unit_id=356173060289134&date=2015-11-13 
         * AnalystService?Operation=GetTractorUtilization&user=telemetry&unit_id=356173060289134&from=2015-11-13&to=2015-11-15
         * 
         * AnalystService?Operation=GetTractorWorkday&user=telemetry&unit_id=356173060289134&&date=2015-11-13
         * AnalystService?Operation=GetTractorWorkday&user=telemetry&unit_id=356173060289134&date=2015-11-20&minstop=00:05:00&minwork=00:20:00&outtime=00:03:00
         * 
         * AnalystService?Operation=GetActivitiesFieldOverview&user=telemetry&site_id=
         * AnalystService?Operation=GetActivitiesFieldOverview&user=telemetry&plot_id=38
         * AnalystService?Operation=GetActivitiesFieldOverviewByPoint&user=telemetry&point=1937361.9561476,6372948.5040346
         * AnalystService?Operation=GetActivitiesFieldOverviewPeriod&user=telemetry&point=1937361.9561476,6372948.5040346&from=2016-05-10&to=2016-05-13
         * 
         * AnalystService?Operation=GetFieldFuelSummary&user=telemetry&point=1937361.9561476,6372948.5040346&from=2016-05-10&to=2016-05-13
         * 
         * AnalystService?Operation=GetManagementZonesOverview&user=telemetry&plot_id=38&unit_id=356173060289134&from=2015-11-20&to=2015-11-30&property_name=yield potential 5m
         * AnalystService?Operation=GetManagementZonesOverview&user2=telemetry&plot_id=38&from=2015-11-20&to=2015-11-30&property_name=yield potential 5m
         * 
         * AnalystService?Operation=GetManagementZonesOverviewByPoint&user=telemetry&point=1937361.9561476,6372948.5040346&unit_id=356173060289134&from=2015-11-20&to=2015-11-30&property_name=yield potential 5m
         * AnalystService?Operation=GetManagementZonesOverviewByPoint2&user=telemetry&point=1937361.9561476,6372948.5040346&from=2015-11-20&to=2015-11-30&property_name=yield potential 5m
         * 
         * AnalystService?Operation=GetDailyFieldActivities&user=telemetry&plot_id=38&from=2015-11-20&to=2015-11-30
         * AnalystService?Operation=GetDailyFieldActivitiesByPoint&user=telemetry&point=1937361.9561476,6372948.5040346&from=2015-11-20&to=2015-11-30
         * 
         * AnalystService?Operation=GetActiveTractorsPeriod&from=2016-05-29&to=2016-06-02&user=telemetry
         * 
         * AnalystService?Operation=GetPlotsGeom&user=telemetry
         * AnalystService?Operation=GetManagementZonesGeom&user=telemetry&plot_id=8
         * AnalystService?Operation=GetManagementZoneGeom&user=telemetry&zone_id=60
         * AnalystService?Operation=GetManagementZoneGeomByPoint&user=telemetry&point=1942324.5738307,6365182.80917219
         * 
         */
        
        /*
         * For FarmTelemetry purpose only temporary authentication
         * */
        RequestParameters params = new RequestParameters(request);
        String user = params.getUsername();
        if(user == null){
            throw new ServletException("Authentication fairlure for request "+ request.getQueryString());
        }
        else{
            try {
                String testLang = db.userUtil.getUserLanguage(user);
                if(testLang.isEmpty()){
                    throw new ServletException("Authentication fairlure for request "+ request.getQueryString());
                }
            } catch (SQLException | NoItemFoundException e1) {
                throw new ServletException("Authentication fairlure for request "+ request.getQueryString());
            }
        }
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json; charset=UTF-8");

        PrintWriter out = response.getWriter();
        try{
            // request GetWorkOnSites
            switch (request.getParameter(ServiceParameters.OPERATION)) {
                case GET_WORK_ON_SITES: {
                    if (params.getDate() != null) {
                        if (!params.getDate().isEmpty()) {
                            DBJsonUtils.writeJSON(out, db.analystUtil.getWorkDurationOnSites(user, params.getDate(), params.getUnit_id()));
                        } else {
                            throw new ServletException("Given parameter \"date\" is empty! In request:" + request.getQueryString());
                        }
                    } else if (params.getFromDate() != null || params.getToDate() != null) {
                        if (!params.getFromDate().isEmpty() || !params.getToDate().isEmpty()) {
                            DBJsonUtils.writeJSON(out, db.analystUtil.getWorkDurationOnSitesPeriod(user, params.getFromDate(), params.getToDate(), params.getUnit_id()));
                        } else {
                            throw new ServletException("Given parameters \"from\" and \"to\" are empty! In request:" + request.getQueryString());
                        }
                    } else {
                        throw new ServletException("Wrong combination of parameters! In request:" + request.getQueryString());
                    }
                } break;
                // request GetTractorUtilization
                case GET_TRACTOR_UTILIZATION: {
                    if (params.getDate() != null) {
                        if (!params.getDate().isEmpty()) {
                            DBJsonUtils.writeJSON(out, db.analystUtil.getUnitUtilization(user, params.getDate(), params.getUnit_id()));
                        } else {
                            throw new ServletException("Given parameter \"date\" is empty! In request:" + request.getQueryString());
                        }
                    } else if (params.getFromDate() != null || params.getToDate() != null) {
                        if (!params.getFromDate().isEmpty() || !params.getToDate().isEmpty()) {
                            DBJsonUtils.writeJSON(out, db.analystUtil.getUnitUtilizationInPeriod(user, params.getFromDate(), params.getToDate(), params.getUnit_id()));
                        } else {
                            throw new ServletException("Given parameters \"from\" and \"to\" are empty! In request:" + request.getQueryString());
                        }
                    } else {
                        throw new ServletException("Wrong combination of parameters! In request:" + request.getQueryString());
                    }
                } break;
                // request GetTractorWorkday
                case GET_TRACTOR_WORKDAY: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getTractorWorkDay(user, params.getDate(), params.getUnit_id(), params.getMinStopDuration(), params.getMinWorkDuration(), params.getAllowedTimeOutside()));
                } break;
                // request GetActivitiesFieldOverview
                case GET_FIELD_OVERVIEW: {
                    if (params.getSiteId() != null) {
                        DBJsonUtils.writeJSON(out, db.analystUtil.getActivitiesFieldOverview(params.getSiteId()));
                    } else if (params.getPlotId() != null) {
                        DBJsonUtils.writeJSON(out, db.analystUtil.getActivitiesFieldOverviewByPlot(params.getPlotId()));
                    }
                } break;
                // request GetActivitiesFieldOverviewByPoint
                case GET_FIELD_OVERVIEW_POINT: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getActivitiesFieldOverviewByPoint(params.getPoint()));
                } break;
                // request GetActivitiesFieldOverviewPeriod
                case GET_FIELD_OVERVIEW_PERIOD: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getActivitiesFieldOverviewPeriodByPoint(params.getPoint(), params.getFromDate(), params.getToDate()));
                } break;
                // request GetFieldFuelSummary
                case GET_FIELD_OVERVIEW_FUEL: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getFieldFuelSummaryByPoint(params.getPoint(), params.getFromDate(), params.getToDate()));
                } break;
                // GetTractorActivePeriod
                case GET_TRACTOR_ACTIVE_PERIOD: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.isTractorActiveInPeriod(user, params.getUnit_id(), params.getFromDate(), params.getToDate()));
                } break;
                // GetActiveTractorsPeriod
                case GET_ACTIVE_TRACTORS_PERIOD: {
                    DBJsonUtils.writeJSONfromList(out, db.analystUtil.getActiveTractorsDuringPeriod(user, params.getFromDate(), params.getToDate()));
                } break;
                // GetManagementZonesOverview with tractor
                case GET_MANAGEMENT_ZONES_OVERVIEW: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getManagementZonesOverviewByPlotId(params.getPlotId(), params.getUnit_id(), params.getFromDate(), params.getToDate(), params.getPropertyName()));
                } break;
                // GetManagementZonesOverview without tractor
                case GET_MANAGEMENT_ZONES_OVERVIEW_2: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getManagementZonesOverviewByPlotId2(params.getPlotId(), params.getFromDate(), params.getToDate(), params.getPropertyName()));
                } break;
                // GetManagementZonesOverviewByPoint with tractor
                case GET_MANAGEMENT_ZONES_OVERVIEW_POINT: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getManagementZonesOverviewByPoint(params.getPoint(), params.getUnit_id(), params.getFromDate(), params.getToDate(), params.getPropertyName()));
                } break;
                // GetManagementZonesOverviewByPoint without tractor
                case GET_MANAGEMENT_ZONES_OVERVIEW_POINT_2: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getManagementZonesOverviewByPoint2(params.getPoint(), params.getFromDate(), params.getToDate(), params.getPropertyName()));
                } break;
                // GetDailyFieldActivities
                case GET_DAILY_FIELD_ACTIVITIES: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getDailyFieldActivities(params.getPlotId(), params.getFromDate(), params.getToDate()));
                } break;
                // GetDailyFieldActivitiesByPoint
                case GET_DAILY_FIELD_ACTIVITIES_POINT: {
                    DBJsonUtils.writeJSON(out, db.analystUtil.getDailyFieldActivitiesByPoint(params.getPoint(), params.getFromDate(), params.getToDate()));
                } break;
                // GetPlotsGeom
                case GET_PLOTS_GEOM: {
                    out.write(db.analystUtil.getPlotsAsGeoJSON().toString());
                } break;
                // GetManagementZonesGeom
                case GET_MAN_ZONES_GEOM: {
                    out.write(db.analystUtil.getManagementZonesGeoJSON(params.getPlotId()).toString());
                } break;
                // GetManagementZoneGeom
                case GET_MAN_ZONE_GEOM: {
                    out.write(db.analystUtil.getManagementZoneGeoJSON(params.getZoneId()).toString());
                } break;
                // GetManagementZoneGeomByPoint
                case GET_MAN_ZONE_GEOM_POINT: {
                    out.write(db.analystUtil.getManagementZoneGeoJSONByPoint(params.getPoint()).toString());
                } break;
                default:
                    throw new NullPointerException("No operation specified.");
            }
        } catch (SQLException | NoItemFoundException e){
            solveGetException(e, out);
        }
    }

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

    static class RequestParameters {

        private final long unit_id;
        private final String date;
        private final String fromDate;
        private final String toDate;
        private final String username;
        private final String minStopDuration;
        private final String minWorkDuration;
        private final String allowedTimeOutside;
        private final Integer siteId;
        private final Integer plotId;
        private final Integer zoneId;
        private final String point;
        private final String propertyName;

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

            Object dateO = request.getParameter("date");
            this.date = dateO != null ? dateO.toString() : null;

            Object fromO = request.getParameter("from");
            this.fromDate = fromO != null ? fromO.toString() : null;

            Object toO = request.getParameter("to");
            this.toDate = toO != null ? toO.toString() : null;

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

            Object minStopO = request.getParameter("minstop");
            this.minStopDuration = minStopO != null ? minStopO.toString() : null;

            Object minWorkO = request.getParameter("minwork");
            this.minWorkDuration = minWorkO != null ? minWorkO.toString() : null;

            Object timeOutO = request.getParameter("outtime");
            this.allowedTimeOutside = timeOutO != null ? timeOutO.toString() : null;

            Object siteIdO = request.getParameter("site_id");
            this.siteId = siteIdO != null ? Integer.valueOf(siteIdO.toString()) : null;

            Object plotIdO = request.getParameter("plot_id");
            this.plotId = plotIdO != null ? Integer.valueOf(plotIdO.toString()) : null;

            Object zoneIdO = request.getParameter("zone_id");
            this.zoneId = zoneIdO != null ? Integer.valueOf(zoneIdO.toString()) : null;

            Object pointO = request.getParameter("point");
            this.point = pointO != null ? pointO.toString() : null;

            Object propertyO = request.getParameter("property_name");
            this.propertyName = propertyO != null ? propertyO.toString() : null;
        }

        public long getUnit_id() {
            return unit_id;
        }
        
        public String getDate(){
            return date;
        }
        
        public String getFromDate(){
            return fromDate;
        }
        
        public String getToDate(){
            return toDate;
        }
        
        public String getUsername(){
            return username;
        }

        public String getMinStopDuration() {
            return minStopDuration;
        }

        public String getMinWorkDuration() {
            return minWorkDuration;
        }

        public String getAllowedTimeOutside() {
            return allowedTimeOutside;
        }

        public Integer getSiteId(){
            return siteId;
        }

        public Integer getPlotId(){
            return plotId;
        }

        public Integer getZoneId(){
            return zoneId;
        }

        public String getPoint() {
            return point;
        }

        public String getPropertyName() {
            return propertyName;
        }

        @Override
        public String toString() {
            return "RequestParameters [unit_id=" + unit_id + ", date=" + date
                         + ", fromDate=" + fromDate + ", toDate=" + toDate
                         + ", username=" + username + ", minStopDuration="
                         + minStopDuration + ", minWorkDuration=" + minWorkDuration
                         + ", allowedTimeOutside=" + allowedTimeOutside
                         + ", siteId=" + siteId + ", point=" + point + "]";
          }
    }
}