package org.exoplatform.cs.portlet.ticketCharts;

import juzu.*;
import juzu.plugin.jackson.Jackson;
import juzu.template.Template;
import org.exoplatform.commons.juzu.ajax.Ajax;
import org.exoplatform.cs.dao.LogDAO;
import org.exoplatform.cs.dto.*;
import org.exoplatform.cs.entity.LogEntity;
import org.exoplatform.cs.entity.SpaceEntity;
import org.exoplatform.cs.portlet.common.CSControllerBase;
import org.exoplatform.cs.service.CSConstants;
import org.exoplatform.cs.service.CSSpaceService;
import org.exoplatform.cs.service.StatsService;
import org.exoplatform.cs.service.TicketService;
import org.exoplatform.cs.service.tickets.FlowState;
import org.exoplatform.cs.service.tickets.TicketStatusFlowService;
import org.exoplatform.cs.service.util.CSUtils;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.User;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import javax.inject.Inject;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;


public class TicketChartsController extends CSControllerBase {

  private static Log  LOG = ExoLogger.getLogger(TicketChartsController.class);
  private String     bundleString;
  ResourceBundle     bundle;
  private List<String> statusList = new ArrayList<String>();
    SimpleDateFormat byDayDateFormat = new SimpleDateFormat("yyyy.MM.dd");
    SimpleDateFormat byMonthDateFormat = new SimpleDateFormat("MMM yyyy");
    SimpleDateFormat byWeekDateFormat = new SimpleDateFormat("YYYY-'W'ww");

    @Inject
  TicketService ticketService;


  @Inject
  TicketStatusFlowService ticketStatusFlowService;

  @Inject
  CSSpaceService spaceService;

  @Inject
  StatsService statsService;


  @Inject
  LogDAO logDao;


    @Inject
    @Path("index.gtmpl")
    Template            indexTmpl;

    @View
    public Response.Content index() {
        return indexTmpl.ok();
    }




    @Ajax
    @Resource
    @MimeType.JSON
    @Jackson
    public Response getBundle(String locale) {
        return super.getBundle(new Locale(locale));
    }


  /**
   * this method returns the static list of ticket types
   *
   * @return
   */
  @Ajax
  @Resource(method = HttpMethod.GET )
  @MimeType.JSON
  @Jackson
  public Map<String, List<FlowState>> loadStatuses() {
    return ticketStatusFlowService.getAllStatuses();
  }




    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response countSpaceTicketsGroupdByOwner(String spaceId) {
        try {
            JSONArray TicketsNumber = new JSONArray();
            List<Object[]> results =ticketService.countSpaceTicketsGroupdByOwner(spaceId);
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                data.put("owner",((Owner) arr[0])!=null ? ((Owner) arr[0]).name() : "Null");
                data.put("ticketNumber",(Long)arr[1]);
                TicketsNumber.put(data);
            }


            return Response.ok(TicketsNumber.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

       @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response countSpaceTicketsGroupdByAssignee(String spaceId) {
        try {
            JSONArray TicketsNumber = new JSONArray();
            List<Object[]> results =ticketService.countSpaceTicketsGroupdByAssignee(spaceId);
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                String assignee = ((String) arr[0])!=null ? ((String) arr[0]).toString() : "Not Assigned";
                data.put("assignee",assignee);
                data.put("ticketNumber",(Long)arr[1]);
                TicketsNumber.put(data);
            }


            return Response.ok(TicketsNumber.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response countSpaceTicketsGroupdByStatus(String spaceId) {
        try {
            JSONArray spaceTicketsNumberByStatus = new JSONArray();
            List<Object[]> results =ticketService.countSpaceTicketsGroupdByStatus(spaceId);
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                data.put("status",(((String) arr[0]).toString()));
                data.put("ticketNumber",(Long)arr[1]);
                spaceTicketsNumberByStatus.put(data);
            }


            return Response.ok(spaceTicketsNumberByStatus.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdByByAssignee(String spaceId) {
        try {
            JSONArray TicketsNumber = new JSONArray();
            List<Object[]> results =ticketService.countSpaceTicketsGroupdByAssignee(spaceId);
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                String assignee = ((String) arr[0])!=null ? ((String) arr[0]).toString() : "Not Assigned";
                data.put("assignee",assignee);
                data.put("ticketNumber",(Long)arr[1]);
                TicketsNumber.put(data);
            }


            return Response.ok(TicketsNumber.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdBySpace() {
        try {
            JSONArray ticketsNumberBySpaceList = new JSONArray();
            List<Object[]> results =ticketService.countCustomerTicketsGroupdBySpace();
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                SpaceDTO spaceDTO = spaceService.getSpace((((SpaceEntity) arr[0]).getGroupId()));
                data.put("space",spaceDTO.getName());
                data.put("ticketNumber",(Long)arr[1]);
                ticketsNumberBySpaceList.put(data);
            }

            return Response.ok(ticketsNumberBySpaceList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }



    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdByAssignee(Long startDate, Long endDate) {
        try {
            List<Object[]> results = new ArrayList<>();
            if(startDate==0 || endDate==0){
                results =ticketService.countCustomerTicketsGroupdByAssigne();
            }else{
                Calendar fromDate=Calendar.getInstance();
                fromDate.setTimeInMillis(startDate);
                Calendar toDate=Calendar.getInstance();
                toDate.setTimeInMillis(startDate);
                results =ticketService.countCustomerTicketsGroupdByAssigneeAndDates(fromDate,toDate);
            }
            JSONArray TicketsNumber = new JSONArray();
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                String assignee = ((String) arr[0])!=null ? ((String) arr[0]).toString() : "Not Assigned";
                data.put("assignee",assignee);
                data.put("ticketNumber",(Long)arr[1]);
                TicketsNumber.put(data);
            }


            return Response.ok(TicketsNumber.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdBySeverity(Long startDate, Long endDate) {
        try {
            List<Object[]> results = new ArrayList<>();
            if(startDate==0 || endDate==0){
                results =ticketService.countCustomerTicketsGroupdBySeverity();
            }else{
                Calendar fromDate=Calendar.getInstance();
                fromDate.setTimeInMillis(startDate);
                Calendar toDate=Calendar.getInstance();
                toDate.setTimeInMillis(startDate);
                results =ticketService.countCustomerTicketsGroupdBySeverityAndDates(fromDate,toDate);
            }
            JSONArray TicketsNumber = new JSONArray();
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                String severity = ((IssueSeverity) arr[0])!=null ? ((IssueSeverity) arr[0]).toString() : "None";
                data.put("severity",severity);
                data.put("ticketNumber",(Long)arr[1]);
                TicketsNumber.put(data);
            }


            return Response.ok(TicketsNumber.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdByOwner() {
        try {
            JSONArray ticketsNumberByOwnerList = new JSONArray();
            List<Object[]> results =ticketService.countCustomerTicketsGroupdByOwner();
            for (int i = 0; i < results.size(); i++) {
                try {
                    Object[] arr = results.get(i);
                    JSONObject data = new JSONObject();
                    if(arr[0]!=null){
                        data.put("owner",(((Owner) arr[0]).name()));
                    }else{
                        data.put("owner","null");
                    }
                    data.put("ticketNumber",(Long)arr[1]);
                    ticketsNumberByOwnerList.put(data);
                } catch (Exception e) {
                }
            }

            return Response.ok(ticketsNumberByOwnerList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdByStatus() {
        try {
            JSONArray ticketsNumberByStatusList = new JSONArray();
            List<Object[]> results =ticketService.countCustomerTicketsGroupdByStatus();
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                data.put("status",(((String) arr[0]).toString()));
                data.put("ticketNumber",(Long)arr[1]);
                ticketsNumberByStatusList.put(data);
            }

            return Response.ok(ticketsNumberByStatusList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerOpenVsClosedTickets() {
        try {
            JSONArray ticketsNumberClosedVsOpenedList = new JSONArray();
            Long closed =ticketService.getCustomerClosedTicketsCount();
            Long opened =ticketService.getCustomerOpenTicketsCount();

                JSONObject data = new JSONObject();
                data.put("status","closed");
                data.put("ticketNumber",closed);
            ticketsNumberClosedVsOpenedList.put(data);
                data = new JSONObject();
                data.put("status","opened");
                data.put("ticketNumber",opened);
            ticketsNumberClosedVsOpenedList.put(data);
            return Response.ok(ticketsNumberClosedVsOpenedList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getOpenVSClosedStatLog(String period, String type, Long startDate, Long endDate) {
        try {
            Calendar fromDate=null;

            if(startDate!=0){
                fromDate=Calendar.getInstance();
                fromDate.setTimeInMillis(startDate);
                fromDate.set(Calendar.HOUR_OF_DAY, 0);
                fromDate.set(Calendar.MINUTE, 0);
                fromDate.set(Calendar.SECOND, 0);
            }

            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            JSONArray ticketsNumberClosedVsOpenedList = new JSONArray();

            List<StatLogDTO> dates = new ArrayList<StatLogDTO>();
            if(period.equals("daily")){
                dates=  statsService.getAllStatsByType("closedTikets",fromDate,toDate);
            }else if(period.equals("monthly")){
                dates=  statsService.getMonthlyStatsByType("closedTikets",fromDate,toDate);
            }else{
                dates=  statsService.getWeeklyStatsByType("closedTikets",fromDate,toDate);
            }
            if(type.equals("charge")){
                Calendar from=null;
                if (fromDate!=null){
                    from=Calendar.getInstance();
                    from.setTime(fromDate.getTime());
                }

                Calendar to=Calendar.getInstance();
                Calendar now= Calendar.getInstance();
                for(StatLogDTO date : dates){
                    if (from==null){
                        from=Calendar.getInstance();
                        from.setTime(((Calendar)date.getStatDate()).getTime());
                    }
                    to.setTime(((Calendar)date.getStatDate()).getTime());
                    if(sameDay(now,to)){
                        to.setTime(now.getTime());
                    }
                    JSONObject data = new JSONObject();
                    data.put("statDate",(getDateByPeriod(((Calendar)date.getStatDate()).getTime(),period)));
                    data.put("closedTicketNumber",logDao.countLogsNumberBetweenDates(from,to,LogType.TICKET_STATUS_CHANGED, CSConstants.STATUS_CLOSED).longValue());
                    data.put("openedTicketNumber",logDao.countLogsNumberBetweenDates(from,to,LogType.TICKET_CREATED).longValue());
                    ticketsNumberClosedVsOpenedList.put(data);
                    from.setTime(((Calendar)date.getStatDate()).getTime());
                }
            }else{
                for(StatLogDTO date : dates){
                    List<StatLogDTO> open = statsService.getStatsByTypeAndDate("openedTikets", date.getStatDate());
                    List<StatLogDTO> close = statsService.getStatsByTypeAndDate("closedTikets", date.getStatDate());
                    JSONObject data = new JSONObject();
                    data.put("statDate",(getDateByPeriod(((Calendar)date.getStatDate()).getTime(),period)));
                    data.put("closedTicketNumber",close.get(0).getTicketsNumber());
                    data.put("openedTicketNumber",open.get(0).getTicketsNumber());
                    ticketsNumberClosedVsOpenedList.put(data);
                }
            }

            return Response.ok(ticketsNumberClosedVsOpenedList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    public boolean sameDay(Calendar cal1, Calendar cal2){
        return cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getLogbyStatusChartData(String period, Long startDate, Long endDate) {
        try {
            Calendar fromDate=null;

            if(startDate!=0){
                fromDate=Calendar.getInstance();
                fromDate.setTimeInMillis(startDate);
                fromDate.set(Calendar.HOUR_OF_DAY, 0);
                fromDate.set(Calendar.MINUTE, 0);
                fromDate.set(Calendar.SECOND, 0);
            }

            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            JSONArray ticketsNumberByStatusList = new JSONArray();
            List<StatLogDTO> dates = new ArrayList<StatLogDTO>();
            if(period.equals("daily")){
                dates=  statsService.getAllStatsByType("tiketsByStatus",fromDate,toDate);
            }else if(period.equals("monthly")){
                dates=  statsService.getMonthlyStatsByType("tiketsByStatus",fromDate,toDate);
            }else{
                dates=  statsService.getWeeklyStatsByType("tiketsByStatus",fromDate,toDate);
            }

            for(StatLogDTO date : dates){
                List<StatLogDTO> logs = statsService.getStatsByTypeAndDate("tiketsByStatus", date.getStatDate());
                JSONObject data = new JSONObject();
                data.put("openedTicketNumber",0);
                data.put("waitingCustomerTicketNumber",0);
                data.put("waitingProductTicketNumber",0);
                data.put("inProgressTicketNumber",0);
                data.put("resolvedTicketNumber",0);
                data.put("closedTicketNumber",0);
                data.put("statDate",(getDateByPeriod(((Calendar)date.getStatDate()).getTime(),period)));
                for(StatLogDTO log : logs){
                    switch (log.getStatus()) {

                        case "open":
                            data.put("openedTicketNumber",log.getTicketsNumber());
                            break;
                        case "suspended_wfi":
                            data.put("waitingCustomerTicketNumber",log.getTicketsNumber());
                            break;
                        case "resolved_maintenance":
                            data.put("waitingProductTicketNumber",log.getTicketsNumber());
                            break;
                        case "inprogress":
                            data.put("inProgressTicketNumber",log.getTicketsNumber());
                            break;
                        case "resolved_validated":
                            data.put("resolvedTicketNumber",log.getTicketsNumber());
                            break;
/*                        case "closed":
                            data.put("closedTicketNumber",log.getTicketsNumber());
                            break;*/

                    }

                }

                ticketsNumberByStatusList.put(data);
            }
            return Response.ok(ticketsNumberByStatusList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerOpenVsClosedTicketsByDates(Long startDate, Long endDate) {
        try {
            JSONArray ticketsNumberClosedVsOpenedList = new JSONArray();
            Calendar cFrom =  Calendar.getInstance();
            cFrom.setTimeInMillis(startDate);
            Calendar cTo =  Calendar.getInstance();
            cTo.setTimeInMillis(endDate);

            Long closed =ticketService.getCustomerClosedTicketsCountByDates(cFrom,cTo);
            Long opened =ticketService.getCustomerOpenTicketsCountByDates(cFrom,cTo);

            JSONObject data = new JSONObject();
            data.put("status","closed");
            data.put("ticketNumber",closed);
            ticketsNumberClosedVsOpenedList.put(data);
            data = new JSONObject();
            data.put("status","opened");
            data.put("ticketNumber",opened);
            ticketsNumberClosedVsOpenedList.put(data);
            return Response.ok(ticketsNumberClosedVsOpenedList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getCustomerTicketsGroupdByStatusAndDates(Long startDate, Long endDate) {
        try {
            JSONArray ticketsNumberByStatusList = new JSONArray();
            Calendar cFrom =  Calendar.getInstance();
            cFrom.setTimeInMillis(startDate);
            Calendar cTo =  Calendar.getInstance();
            cTo.setTimeInMillis(endDate);

            List<Object[]> results =ticketService.countCustomerTicketsGroupdByStatusAndDates(cFrom,cTo);
            for (int i = 0; i < results.size(); i++) {
                Object[] arr = results.get(i);
                JSONObject data = new JSONObject();
                data.put("status",(((String) arr[0]).toString()));
                data.put("ticketNumber",(Long)arr[1]);
                ticketsNumberByStatusList.put(data);
            }

            return Response.ok(ticketsNumberByStatusList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }




    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getData() {
        try {
                JSONObject data = new JSONObject();
                String curentSpace = getCurrentSpaceId();
                if(curentSpace!=null && curentSpace.equals("/spaces/exo_support")) curentSpace = null;
                data.put("currentSpace",curentSpace);
            if(curentSpace==null){
                long stisfied = ticketService.countSatisfiedTicketNumber().longValue();
                long notStisfied = ticketService.countNotSatisfiedTicketNumber().longValue();
                long total = stisfied+notStisfied;
                if(total>0){
                    data.put("customerSatisfactionPrc",stisfied*100/total);
                    data.put("customerTotalVotes",total);
                }else{
                    data.put("customerSatisfactionPrc","--");
                }
                data.put("firstTimeResponceAverage",ticketService.getTimeToFirstResponseAvg().longValue());
                data.put("timeToResolutionAverage",ticketService.getTimeToResolutionAvg().longValue());
            }else{
                long stisfied = ticketService.countSpaceSatisfiedTicketNumber(curentSpace).longValue();
                long notStisfied = ticketService.countSpaceNotSatisfiedTicketNumber(curentSpace).longValue();
                long total = stisfied+notStisfied;
                if(total>0){
                    data.put("customerSatisfactionPrc",stisfied*100/total);
                    data.put("customerTotalVotes",total);
                    data.put("firstTimeResponceAverage",ticketService.getSpaceTimeToFirstResponseAvg(curentSpace).longValue());
                    data.put("timeToResolutionAverage",ticketService.getSpaceTimeToResolutionAvg(curentSpace).longValue());
                }else{
                    data.put("customerSatisfactionPrc","--");
                    data.put("customerTotalVotes",total);
                }
            }


            return Response.ok(data.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }




    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getMetricsByDates(Long startDate, Long endDate) {
        try {
            Calendar fromDate=Calendar.getInstance();
            fromDate.setTimeInMillis(startDate);
            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            JSONObject data = new JSONObject();
            long stisfied = logDao.countLogsNumberBetweenDates(fromDate,toDate,LogType.CUSTOMER_SATISFACTION_ADDED,"false").longValue();
            long notStisfied = logDao.countLogsNumberBetweenDates(fromDate,toDate,LogType.CUSTOMER_SATISFACTION_ADDED,"true").longValue();
            long total = stisfied+notStisfied;
                if(total>0){
                    data.put("customerSatisfactionPrc",stisfied*100/total);
                    data.put("customerTotalVotes",total);
                }else{
                    data.put("customerSatisfactionPrc","--");
                    data.put("customerTotalVotes",total);
                }
                data.put("firstTimeResponceAverage",logDao.getTimeToFirstResponseAvgBetweenDates(fromDate,toDate));
                data.put("timeToResolutionAverage",logDao.getTimeToResolutionAvgBetweenDates(fromDate,toDate));
            return Response.ok(data.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getSpaceMetricsData(String currentSpace) {
        try {
            JSONObject data = new JSONObject();
            long stisfied = ticketService.countSpaceSatisfiedTicketNumber(currentSpace).longValue();
            long notStisfied = ticketService.countSpaceNotSatisfiedTicketNumber(currentSpace).longValue();
            long total = stisfied+notStisfied;
            if(total>0){
                data.put("customerSatisfactionPrc",stisfied*100/total);
                data.put("customerTotalVotes",total);
                data.put("firstTimeResponceAverage",ticketService.getSpaceTimeToFirstResponseAvg(currentSpace).longValue());
                data.put("timeToResolutionAverage",ticketService.getSpaceTimeToResolutionAvg(currentSpace).longValue());
            }else{
                data.put("customerSatisfactionPrc","--");
                data.put("customerTotalVotes",total);
            }
            return Response.ok(data.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    public String getTimeInDaysMunitsAndSecondes(long millis){
        long days = TimeUnit.MILLISECONDS.toDays(millis);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
        return "Time left:" + days + ":" + hours + ":" + minutes + ":" + seconds;
    }


    /**
     * This service will return the names of all support team members
     * @param ticketDTO
     * @return
     */
    @Ajax
    @Resource(method = HttpMethod.GET)
    @MimeType.JSON
    @Jackson
    public List<User> getSupportUsernames(@Jackson TicketDTO ticketDTO) {
        try {
            return CSUtils.getSupportMembers();
        } catch (Throwable e) {
            LOG.error("Can't retrieve the list of support engineers " + e);
            return null;
        }
    }

    /**
   * this method returns the list of customer spaces
   *
   * @return
   */
  @Ajax
  @Resource(method = HttpMethod.GET )
  @MimeType.JSON
  @Jackson
  public List<SpaceDTO> getSpaces() {
    return spaceService.getAllSpaces();
  }



    @Override
    public Log getLogger() {
        return LOG;
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getTimeMetricsByWeek(Long startDate, Long endDate) {
        try {
            Calendar fromDate=Calendar.getInstance();
            fromDate.setTimeInMillis(startDate);
            if(startDate==0){
                LogEntity log_ = logDao.getTimeToFirstResponseFirstLog().get(0);
                LogEntity log__ = logDao.getTimeToResolutionFirstLog().get(0);
                if(log_!=null) {
                    fromDate.setTime(log_.getWhen().getTime());
                } else if(log__!=null) {
                    if(log_!=null && log__.getWhen().before(log_.getWhen()))
                    fromDate.setTime(log__.getWhen().getTime());
                } else
                    return Response.notFound();
            }
            JSONArray npsList = new JSONArray();

            fromDate.set(Calendar.HOUR_OF_DAY, 0);
            fromDate.set(Calendar.MINUTE, 0);
            fromDate.set(Calendar.SECOND, 0);
            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            int diff= Calendar.SATURDAY-fromDate.get(Calendar.DAY_OF_WEEK)+2;
            Calendar to_=Calendar.getInstance();
            to_.setTime(fromDate.getTime());
            to_.add(Calendar.DATE, diff);
            while(fromDate.before(toDate)){
                Double ttfs=logDao.getTimeToFirstResponseAvgBetweenDates(fromDate,to_);
                Double ttr=logDao.getTimeToResolutionAvgBetweenDates(fromDate,to_);
                JSONObject ttfs_ = new JSONObject();
                ttfs_.put("timeMetricsDate",getDateByPeriod(fromDate.getTime(),"weekly"));
                ttfs_.put("timeToFirstResponse",ttfs);
                ttfs_.put("timeToResolution",ttr);
                npsList.put(ttfs_);
                fromDate.setTime(to_.getTime());
                to_.add(Calendar.DATE, 7);
            }

            return Response.ok(npsList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getSatisfactionByWeek(Long startDate, Long endDate) {
        try {
            Calendar fromDate=Calendar.getInstance();
            fromDate.setTimeInMillis(startDate);
            if(startDate==0){
                LogEntity log_ = logDao.getFirstLogByType(LogType.CUSTOMER_SATISFACTION_ADDED).get(0);
                if(log_!=null) {
                    fromDate.setTime(log_.getWhen().getTime());
                    } else
                    return Response.notFound();
            }
            JSONArray cSatList = new JSONArray();

            fromDate.set(Calendar.HOUR_OF_DAY, 0);
            fromDate.set(Calendar.MINUTE, 0);
            fromDate.set(Calendar.SECOND, 0);
            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            int diff= Calendar.SATURDAY-fromDate.get(Calendar.DAY_OF_WEEK)+2;
            Calendar to_=Calendar.getInstance();
            to_.setTime(fromDate.getTime());
            to_.add(Calendar.DATE, diff);
            while(fromDate.before(toDate)){

                long stisfied = logDao.countLogsNumberBetweenDates(fromDate,to_,LogType.CUSTOMER_SATISFACTION_ADDED,"false").longValue();
                long notStisfied = logDao.countLogsNumberBetweenDates(fromDate,to_,LogType.CUSTOMER_SATISFACTION_ADDED,"true").longValue();
                long total = stisfied+notStisfied;

                JSONObject data = new JSONObject();
                if(total>0){
                    data.put("satisfactionDate",getDateByPeriod(fromDate.getTime(),"weekly"));
                    data.put("customerSatisfactionPrc",stisfied*100/total);
                    data.put("customerTotalVotes",total);
                }else{
                    data.put("satisfactionDate",getDateByPeriod(fromDate.getTime(),"weekly"));
                    data.put("customerSatisfactionPrc","--");
                    data.put("customerTotalVotes",total);
                }

                cSatList.put(data);
                fromDate.setTime(to_.getTime());
                to_.add(Calendar.DATE, 7);
            }

            return Response.ok(cSatList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getSatisfactionByMonth(Long startDate, Long endDate) {
        try {
            Calendar fromDate=Calendar.getInstance();
            fromDate.setTimeInMillis(startDate);
            if(startDate==0){
                LogEntity log_ = logDao.getFirstLogByType(LogType.CUSTOMER_SATISFACTION_ADDED).get(0);
                if(log_!=null) {
                    fromDate.setTime(log_.getWhen().getTime());
                } else
                    return Response.notFound();
            }
            JSONArray cSatList = new JSONArray();

            fromDate.set(Calendar.HOUR_OF_DAY, 0);
            fromDate.set(Calendar.MINUTE, 0);
            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            Calendar to_=Calendar.getInstance();
            to_.setTime(fromDate.getTime());
            to_.set(Calendar.DAY_OF_MONTH, fromDate.getActualMaximum(Calendar.DAY_OF_MONTH));
            while(fromDate.before(toDate)){
                long stisfied = logDao.countLogsNumberBetweenDates(fromDate,to_,LogType.CUSTOMER_SATISFACTION_ADDED,"false").longValue();
                long notStisfied = logDao.countLogsNumberBetweenDates(fromDate,to_,LogType.CUSTOMER_SATISFACTION_ADDED,"true").longValue();
                long total = stisfied+notStisfied;

                JSONObject data = new JSONObject();
                if(total>0){
                    data.put("satisfactionDate",getDateByPeriod(fromDate.getTime(),"monthly"));
                    data.put("customerSatisfactionPrc",stisfied*100/total);
                    data.put("customerTotalVotes",total);
                }else{
                    data.put("satisfactionDate",getDateByPeriod(fromDate.getTime(),"monthly"));
                    data.put("customerSatisfactionPrc","--");
                    data.put("customerTotalVotes",total);
                }

                cSatList.put(data);
                fromDate.setTime(to_.getTime());
                fromDate.set(Calendar.MONTH,fromDate.get(Calendar.MONTH)+1);
                fromDate.set(Calendar.DAY_OF_MONTH,1);
                to_.setTime(fromDate.getTime());
                to_.set(Calendar.DAY_OF_MONTH, fromDate.getActualMaximum(Calendar.DAY_OF_MONTH));
            }

            return Response.ok(cSatList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getTimeMetricsByMonth(Long startDate, Long endDate) {
        try {
            Calendar fromDate=Calendar.getInstance();
            fromDate.setTimeInMillis(startDate);
            if(startDate==0){
                LogEntity log_ = logDao.getTimeToFirstResponseFirstLog().get(0);
                LogEntity log__ = logDao.getTimeToResolutionFirstLog().get(0);
                if(log_!=null) {
                    fromDate.setTime(log_.getWhen().getTime());
                } else if(log__!=null) {
                    if(log_!=null && log__.getWhen().before(log_.getWhen()))
                    fromDate.setTime(log__.getWhen().getTime());
                } else
                    return Response.notFound();
            }
            JSONArray npsList = new JSONArray();

            fromDate.set(Calendar.HOUR_OF_DAY, 0);
            fromDate.set(Calendar.MINUTE, 0);
            Calendar toDate=Calendar.getInstance();
            toDate.setTimeInMillis(endDate);
            Calendar to_=Calendar.getInstance();
            to_.setTime(fromDate.getTime());
            to_.set(Calendar.DAY_OF_MONTH, fromDate.getActualMaximum(Calendar.DAY_OF_MONTH));
            while(fromDate.before(toDate)){
                Double ttfs=logDao.getTimeToFirstResponseAvgBetweenDates(fromDate,to_);
                Double ttr=logDao.getTimeToResolutionAvgBetweenDates(fromDate,to_);

                JSONObject ttfs_ = new JSONObject();
                ttfs_.put("timeMetricsDate",getDateByPeriod(fromDate.getTime(),"monthly"));
                ttfs_.put("timeToFirstResponse",ttfs);
                ttfs_.put("timeToResolution",ttr);
                npsList.put(ttfs_);
                fromDate.setTime(to_.getTime());
                fromDate.set(Calendar.MONTH,fromDate.get(Calendar.MONTH)+1);
                fromDate.set(Calendar.DAY_OF_MONTH,1);
                to_.setTime(fromDate.getTime());
                to_.set(Calendar.DAY_OF_MONTH, fromDate.getActualMaximum(Calendar.DAY_OF_MONTH));
            }

            return Response.ok(npsList.toString());
        } catch (Throwable e) {
            LOG.error("error while getting context", e);
            return Response.status(500);
        }
    }

public String getDateByPeriod(Date date, String period){
      if(period.equals("weekly")){
          return byWeekDateFormat.format(date);
      }else if(period.equals("monthly")){
          return byMonthDateFormat.format(date);
      }
      return byDayDateFormat.format(date);
}



}
