content: /*
   *  Copyright (C) 2010-2016 Stichting Akvo (Akvo Foundation)
   *
   *  This file is part of Akvo FLOW.
   *
   *  Akvo FLOW is free software: you can redistribute it and modify it under the terms of
   *  the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
   *  either version 3 of the License or any later version.
   *
   *  Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   *  See the GNU Affero General Public License included below for more details.
   *
   *  The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
   */
  
  package org.waterforpeople.mapping.app.web;
  
  import java.io.IOException;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.waterforpeople.mapping.app.web.dto.SurveyManagerRequest;
  import org.waterforpeople.mapping.dao.DeviceFilesDao;
  import org.waterforpeople.mapping.dao.SurveyContainerDao;
  import org.waterforpeople.mapping.dao.SurveyInstanceDAO;
  import org.waterforpeople.mapping.domain.SurveyInstance;
  
  import com.gallatinsystems.common.Constants;
  import com.gallatinsystems.device.dao.DeviceDAO;
  import com.gallatinsystems.device.domain.DeviceFiles;
  import com.gallatinsystems.device.domain.DeviceSurveyJobQueue;
  import com.gallatinsystems.framework.rest.AbstractRestApiServlet;
  import com.gallatinsystems.framework.rest.RestRequest;
  import com.gallatinsystems.framework.rest.RestResponse;
  import com.gallatinsystems.survey.dao.DeviceSurveyJobQueueDAO;
  import com.gallatinsystems.survey.dao.SurveyDAO;
  import com.gallatinsystems.survey.dao.SurveyGroupDAO;
  import com.gallatinsystems.survey.domain.Survey;
  import com.gallatinsystems.survey.domain.SurveyContainer;
  import com.gallatinsystems.survey.domain.SurveyGroup;
  
  public class SurveyManagerServlet extends AbstractRestApiServlet {
      private static final Logger log = Logger
              .getLogger(SurveyManagerServlet.class.getName());
      private static final long serialVersionUID = 4400244780977729721L;
  
      private DeviceDAO deviceDao;
  
      public SurveyManagerServlet() {
          super();
          deviceDao = new DeviceDAO();
          setMode(AbstractRestApiServlet.XML_MODE);
      }
  
      @Override
      protected RestRequest convertRequest() throws Exception {
          HttpServletRequest req = getRequest();
          RestRequest restRequest = new SurveyManagerRequest();
          restRequest.populateFromHttpRequest(req);
          return restRequest;
      }
  
      @Override
      protected RestResponse handleRequest(RestRequest req) throws Exception {
          // TODO: this API should be refactored to always take an ACTION
          SurveyManagerRequest mgrReq = (SurveyManagerRequest) req;
          RestResponse resp = new RestResponse();
          if (mgrReq.getAction() == null) {
              if (mgrReq.getSurveyDoc() != null) {
                  // resp.setMessage("Survey : "
                  // + surveyDAO.save(mgrReq.getSurveyDoc()));
              } else if (mgrReq.getSurveyInstanceId() != null) {
                  SurveyInstanceDAO siDAO = new SurveyInstanceDAO();
                  SurveyInstance si = siDAO
                          .getByKey(mgrReq.getSurveyInstanceId());
                  if (si != null) {
                      resp.setMessage(si.toString());
                  } else {
                      resp.setMessage("No Survey Instance Found");
                  }
  
              } else if (mgrReq.getSurveyId() != null) {
                  SurveyContainerDao scDao = new SurveyContainerDao();
                  SurveyContainer container = scDao.findBySurveyId(mgrReq
                          .getSurveyId());
                  if (container != null) {
  
                      resp.setMessage(container.getSurveyDocument().getValue());
                  } else {
                      resp.setMessage("No Survey Found");
                  }
              }
  
          } else if (SurveyManagerRequest.GET_AVAIL_DEVICE_SURVEY_ACTION
                  .equalsIgnoreCase(req.getAction())) {
              // Report which surveys the device should have
              if (mgrReq.getPhoneNumber() != null || mgrReq.getImei() != null) {
                  resp.setMessage(getSurveyForPhone(mgrReq.getPhoneNumber(), mgrReq.getImei(),
                          mgrReq.getAndroidId()));
  
                  // Update last connection time, or register device if needed
                  deviceDao.updateDevice(mgrReq.getPhoneNumber(), null, null, null,
                          mgrReq.getVersion(), mgrReq.getDeviceId(), mgrReq.getImei(), null,
                          mgrReq.getAndroidId());
              }
          } else if (SurveyManagerRequest.GET_AVAIL_DEVICE_SURVEYGROUP_ACTION
                  .equalsIgnoreCase(req.getAction())) {
              // Report which survey groups the device should have
              if (mgrReq.getPhoneNumber() != null || mgrReq.getImei() != null) {
                  resp.setMessage(getSurveyGroupsForPhone(mgrReq.getPhoneNumber(), mgrReq.getImei(),
                          mgrReq.getAndroidId()));
              }
          } else if (SurveyManagerRequest.GET_SURVEY_HEADER_ACTION
                  .equalsIgnoreCase(req.getAction())) {
              if (mgrReq.getSurveyId() != null) {
                  SurveyDAO surveyDao = new SurveyDAO();
                  SurveyGroupDAO sgDao = new SurveyGroupDAO();
                  Survey survey = surveyDao.getById(mgrReq.getSurveyId());
                  String sgName = null;
                  Boolean isInMonitoringGroup = false;
                  String newLocaleSurveyId = "null";
                  if (survey != null) {
                      SurveyGroup sg = sgDao.getByKey(survey.getSurveyGroupId());
                      if (sg != null) {
                          sgName = sg.getCode();
                          isInMonitoringGroup = Boolean.valueOf(sg.getMonitoringGroup() != null ? sg
                                  .getMonitoringGroup() : false);
                          newLocaleSurveyId = sg.getNewLocaleSurveyId() != null ? sg
                                  .getNewLocaleSurveyId().toString() : "null";
                      }
                      StringBuilder sb = new StringBuilder();
                      sb.append(survey.getKey().getId() + ",")
                              .append(survey.getName() != null ? survey.getName()
                                      : "Survey " + survey.getKey().getId())
                              .append(",")
                              .append(survey.getDefaultLanguageCode() != null ? survey
                                      .getDefaultLanguageCode() : "en")
                              .append(",")
                              .append(survey.getVersion() != null ? survey
                                      .getVersion() : "1")
                              .append(",")
                              .append(survey.getSurveyGroupId().toString())
                              .append(",")
                              .append(sgName != null ? sgName : "null")
                              .append(",")
                              .append(isInMonitoringGroup)
                              .append(",")
                              .append(newLocaleSurveyId);
                      resp.setMessage(sb.toString());
                  }
              }
              // Update last connection time, or register device if needed
              deviceDao.updateDevice(mgrReq.getPhoneNumber(), null, null, null,
                      mgrReq.getVersion(), mgrReq.getDeviceId(), mgrReq.getImei(), null,
                      mgrReq.getAndroidId());
          } else if (SurveyManagerRequest.GET_ZIP_FILE_URL_ACTION
                  .equalsIgnoreCase(req.getAction())) {
              DeviceFilesDao dfDao = new DeviceFilesDao();
              List<DeviceFiles> dfList = dfDao.listDeviceFilesByDate(
                      mgrReq.getStartDate(), "all");
              if (dfList != null) {
                  Set<String> uxUrlList = new HashSet<String>();
                  for (DeviceFiles df : dfList) {
  
                      uxUrlList.add(df.getURI());
  
                  }
                  StringBuilder sb = new StringBuilder();
                  for (String item : uxUrlList)
                      sb.append(item + "\n");
                  resp.setMessage(sb.toString());
              }
          }
          return resp;
      }
  
      // Return a list all the surveys the device needs
      // use imei or phone number for lookup
      private String getSurveyForPhone(String devicePhoneNumber, String imei, String androidId) {
          DeviceSurveyJobQueueDAO dsjqDAO = new DeviceSurveyJobQueueDAO();
          SurveyDAO surveyDao = new SurveyDAO();
          SurveyGroupDAO sgDao = new SurveyGroupDAO();
          StringBuilder sb = new StringBuilder();
          String sgName;
          String surveyName;
          Double ver;
          Boolean isInMonitoringGroup;
          String newLocaleSurveyId;
          for (DeviceSurveyJobQueue dsjq : dsjqDAO.get(devicePhoneNumber, imei, androidId)) {
              Survey s = surveyDao.getById(dsjq.getSurveyID());
              SurveyGroup sg = s != null && s.getSurveyGroupId() != null ?
                      sgDao.getByKey(s.getSurveyGroupId())
                      : null;
  
              if (s != null && sg != null) {
                  ver = s.getVersion();
                  surveyName = s.getName();
                  sgName = sg.getCode() != null ? sg.getCode() : "unknown";
                  isInMonitoringGroup = Boolean.valueOf(sg.getMonitoringGroup() != null ? sg
                          .getMonitoringGroup() : false);
                  newLocaleSurveyId = sg.getNewLocaleSurveyId() != null ? sg.getNewLocaleSurveyId()
                          .toString() : "null";
                  if (ver == null) {
                      ver = new Double(1.0);
                  }
  
                  sb.append(devicePhoneNumber + "," + dsjq.getSurveyID() + ","
                          + surveyName + "," + dsjq.getLanguage() + "," + ver
                          + "," + s.getSurveyGroupId() + "," + sgName
                          + "," + isInMonitoringGroup + "," + newLocaleSurveyId
                          + "\n");
              }
          }
          return sb.toString();
      }
  
      // Return a list all the survey groups the device needs
      // use imei or phone number for lookup
      private String getSurveyGroupsForPhone(String devicePhoneNumber, String imei, String androidId) {
          DeviceSurveyJobQueueDAO dsjqDAO = new DeviceSurveyJobQueueDAO();
          SurveyDAO surveyDao = new SurveyDAO();
          SurveyGroupDAO sgDao = new SurveyGroupDAO();
  
          // build map of which surveyGroups to include
          Map<Long, Boolean> includeGroupMap = new HashMap<Long, Boolean>();
          for (DeviceSurveyJobQueue dsjq : dsjqDAO.get(devicePhoneNumber, imei, androidId)) {
              Survey s = surveyDao.getById(dsjq.getSurveyID());
              if (s != null) {
                  includeGroupMap.put(s.getSurveyGroupId(), true);
              }
          }
  
          StringBuilder sb = new StringBuilder();
          for (SurveyGroup sg : sgDao.list(Constants.ALL_RESULTS)) {
              if (includeGroupMap.get(sg.getKey().getId()) != null) {
                  sb.append(sg.getKey().getId())
                          .append(",")
                          .append(sg.getCode())
                          .append(",")
                          .append(Boolean.valueOf(sg.getMonitoringGroup() != null ? sg
                                  .getMonitoringGroup() : false)).append(",")
                          .append(sg.getNewLocaleSurveyId()).append("\n");
              }
          }
          return sb.toString();
      }
  
      @Override
      protected void writeOkResponse(RestResponse response) throws Exception {
          try {
              HttpServletResponse resp = getResponse();
              resp.setStatus(HttpServletResponse.SC_OK);
              resp.getWriter().print(response.getMessage());
          } catch (IOException e) {
              log.log(Level.SEVERE,
                      "Could not write survey manager response to http output stream",
                      e);
          }
      }
  }
  