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.dto.Owner;
import org.exoplatform.cs.dto.SpaceDTO;
import org.exoplatform.cs.dto.StatLogDTO;
import org.exoplatform.cs.dto.TicketDTO;
import org.exoplatform.cs.entity.SpaceEntity;
import org.exoplatform.cs.portlet.common.CSControllerBase;
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.stream.Stream;


public class TicketChartsController extends CSControllerBase {

  private static Log  LOG = ExoLogger.getLogger(TicketChartsController.class);
    private static final DateFormat DATE_FORMAT_TO_CONVERT_USED_FOR_CHARTS = new SimpleDateFormat("yyyy-MM-dd");
  private String     bundleString;
  ResourceBundle     bundle;
  private List<String> statusList = new ArrayList<String>();


    @Inject
  TicketService ticketService;


  @Inject
  TicketStatusFlowService ticketStatusFlowService;

  @Inject
  CSSpaceService spaceService;

  @Inject
  StatsService statsService;


    @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]).name()));
                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 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 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() {
        try {
            JSONArray ticketsNumberClosedVsOpenedList = new JSONArray();
            List<StatLogDTO> dates =statsService.getAllStatsByType("closedTikets",null,null);
            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",(DATE_FORMAT_TO_CONVERT_USED_FOR_CHARTS.format(((Calendar)date.getStatDate()).getTime())));
                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);
        }
    }


    @Ajax
    @juzu.Resource
    @MimeType.JSON
    @Jackson
    public Response getLogbyStatusChartData() {
        try {
            JSONArray ticketsNumberByStatusList = new JSONArray();
            List<StatLogDTO> dates =statsService.getAllStatsByType("tiketsByStatus",null,null);
            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",(DATE_FORMAT_TO_CONVERT_USED_FOR_CHARTS.format(((Calendar)date.getStatDate()).getTime())));
                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);

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



    /**
     * 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;
    }


}
