package org.exoplatform.cs.portlet.ticketAdministration;

import juzu.HttpMethod;
import juzu.MimeType;
import juzu.Path;
import juzu.Resource;
import juzu.Response;
import juzu.View;
import juzu.impl.common.JSON;
import juzu.plugin.jackson.Jackson;
import juzu.template.Template;
import org.exoplatform.commons.juzu.ajax.Ajax;
import org.exoplatform.cs.dto.*;
import org.exoplatform.cs.entity.SpaceEntity;
import org.exoplatform.cs.service.CSSpaceService;
import org.exoplatform.cs.service.sla.Sla;
import org.exoplatform.cs.service.sla.SlaService;
import org.exoplatform.cs.service.subscription.Subscription;
import org.exoplatform.cs.service.subscription.SubscriptionService;
import org.exoplatform.cs.service.util.CSUtils;
import org.exoplatform.cs.portlet.common.CSControllerBase;
import org.exoplatform.cs.service.TicketService;
import org.exoplatform.cs.service.tickets.FlowState;
import org.exoplatform.cs.service.tickets.TicketStatusFlowService;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.mop.SiteType;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.identity.model.Profile;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.space.model.Space;
import org.json.JSONArray;
import org.json.JSONObject;

import javax.inject.Inject;


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.*;


/**
 * Created by exo on 8/3/16.
 */
public class TicketAdministrationController extends CSControllerBase {
  private static Log  LOG = ExoLogger.getLogger(TicketAdministrationController.class);


  @Inject
  TicketService       ticketService;


  @Inject
  TicketStatusFlowService ticketStatusFlowService;

  @Inject
  CSSpaceService spaceService;


  @Inject
  SlaService slaService;

  @Inject
  SubscriptionService subscriptionService;

  @Inject
  IdentityManager identityManager;

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

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

  @Ajax
  @Resource
  @MimeType.JSON
  @Jackson
  public List<TicketDTO> getAllTickets(String filter, String selectedSpace, String selectedStatus) {
    try {
      Calendar from = Calendar.getInstance();
      from.add(Calendar.DATE, -7);
      if(filter.equals("allassignedtickets")){
        return ticketService.getAssignedTickets(getCurrentUser().getUserName(), selectedSpace, true, selectedStatus);
      } else if(filter.equals("allmytickets")){
        return ticketService.getMyTickets(getCurrentUser().getUserName(), selectedSpace, true, selectedStatus);
      } else if (filter.equals("allopentickets"))  {
        return ticketService.getTickets(selectedSpace, false, selectedStatus);
      } else if(filter.equals("alltickets")) {
        return ticketService.getTickets(selectedSpace, true, selectedStatus);
      }else if(filter.equals("assignedopentickets")) {
        return ticketService.getAssignedTickets(getCurrentUser().getUserName(),selectedSpace,false, selectedStatus);
      }else if(filter.equals("lastUpdated")) {
        return ticketService.getUpdatedTickets(selectedStatus,selectedSpace, from, Calendar.getInstance());
      }else if(filter.equals("lastCreated")) {
        return ticketService.getCreatedTickets(selectedSpace,from, Calendar.getInstance());
      }else if(filter.equals("notAssigned")) {
        return ticketService.getNotAssignedTickets(selectedSpace);
      }
      return ticketService.getMyTickets(getCurrentUser().getUserName(),selectedSpace,false, selectedStatus);
    } catch (Throwable e) {
      LOG.error("Exception when retrieving tickets" + e);
      return null;
    }
  }

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

  @Ajax
  @Resource(method = HttpMethod.POST)
  @MimeType.JSON
  @Jackson
  public TicketDTO saveTicket(@Jackson TicketDTO ticketDTO) throws Exception {
    try {
      return ticketService.updateTicket(ticketDTO, getCurrentUser());
    } catch (Exception e) {
      LOG.error("Error when updating ticket", e);
      throw e;
    }
  }

  /**
   * This service will return the names of all support team members
   * @param ticketDTO
   * @return
   */
  @Ajax
  @Resource(method = HttpMethod.POST)
  @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 service will return the names and avatars of all support team members
   * @return
   */

  @Ajax
  @juzu.Resource
  @MimeType.JSON
  @Jackson
  public Response getSupportAgents() {
    try {
      JSONArray agentsList = new JSONArray();

      List<User> agents = CSUtils.getSupportMembers();
      for(User agent :agents){
        JSONObject data = new JSONObject();
        data.put("userName",agent.getUserName());
        data.put("displayName",agent.getDisplayName());
        agentsList.put(data);
      }

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


  /**
   * this method will return the list of severities
   * @return List of ticket severity
   */
  @Ajax
  @Resource(method = HttpMethod.POST)
  @MimeType.JSON
  @Jackson
  public List<String> getSeverities(@Jackson TicketDTO ticketDTO) {
      List<String> severities = new ArrayList<>();
      if(ticketDTO.getType().equals(IssueType.INCIDENT)){
        severities.add(IssueSeverity.SEVERITY_1.name());
        severities.add(IssueSeverity.SEVERITY_2.name());
        severities.add(IssueSeverity.SEVERITY_3.name());
      } else if(ticketDTO.getType().equals(IssueType.INFORMATION)) {
        severities.add(IssueSeverity.SEVERITY_4.name());
      }
      return severities;
  }

  /**
   * this method returns the static list of ticket types
   *
   * @return
   */
  @Ajax
  @Resource(method = HttpMethod.POST)
  @MimeType.JSON
  @Jackson
  public List<String> getTicketTypes() {
      List<String> ticketTypes = new ArrayList<>();
      ticketTypes.add(IssueType.INCIDENT.name());
      ticketTypes.add(IssueType.INFORMATION.name());
      return ticketTypes;
  }


  /**
   * this method returns the static list of Owners
   *
   * @return
   */

  @Ajax
  @Resource(method = HttpMethod.POST)
  @MimeType.JSON
  @Jackson
  public List<String> getOwnersList() {
    List<String> ownersList = new ArrayList<>();
    Owner[] owners = Owner.values();
    for (int i=0; i<owners.length; i++ ){
      ownersList.add(owners[i].name());
    }
      return ownersList;
  }


  /**
   * this method returns the application Context
   *
   * @return
   */

  @Ajax
  @juzu.Resource
  @MimeType.JSON
  @Jackson
  public Response getContext() {
    try {
      JSON data = new JSON();
      String currentSpace=getCurrentSpaceId();
      if(currentSpace == null || currentSpace.equals("/spaces/exo_support")) {
        data.set("currentSpace", "");
        data.set("currentSpaceIncidentFlow", "SIMPLE");
        data.set("currentSpaceInformationFlow", "SIMPLE");
      }
      else{
        data.set("currentSpace", currentSpace);
        SpaceDTO spaceDTO = spaceService.getSpace(currentSpace);
        data.set("currentSpaceIncidentFlow", spaceDTO.getIncidentFlow());
        data.set("currentSpaceInformationFlow", spaceDTO.getInformationFlow());
      }

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

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

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

  @Ajax
  @Resource(method = HttpMethod.POST)
  @MimeType.JSON
  @Jackson
  public String deleteTicket(@Jackson TicketDTO ticket) {
    ticketService.deleteTicket(ticket);
    return "OK";
  }

  public String getCurrentSpaceId() {
    String spaceGroupId = null;
    PortalRequestContext requestContext = Util.getPortalRequestContext();
    if (requestContext != null) {
      if (requestContext.getSiteType().equals(SiteType.GROUP) && requestContext.getSiteName().startsWith("/spaces")) {
        spaceGroupId = requestContext.getSiteName();
      }
    }
    return spaceGroupId;
  }


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