package org.exoplatform.cs.service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;


import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.RuntimeDelegate;
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.RootContainer;
import org.exoplatform.cs.dto.TicketDTO;
import org.exoplatform.platform.common.rest.services.GettingStarted.GettingStartedRestService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rest.impl.RuntimeDelegateImpl;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Created by eXo Platform SAS.
 *
 * @author Ali Hamdi
 * @since 03/04/17
 */
@Path("customerspace")
public class TicketUpdatesService implements ResourceContainer {

  private static final Log LOG = ExoLogger.getLogger(TicketUpdatesService.class);
  private static final CacheControl cc;

  static {
    RuntimeDelegate.setInstance(new RuntimeDelegateImpl());
    cc = new CacheControl();
    cc.setNoCache(true);
    cc.setNoStore(true);
  }

  /**
   * This endpoint will provide the lately updated tickets
   * @param uriInfo URI info
   * @param from Date to get updates from
   * @param to Date to get updates to
   * @return Json array of updated tickets
   */
  @GET
  @RolesAllowed("users")
  @Path("cstickets/updates.json")
  @Produces(MediaType.APPLICATION_JSON)
  public Response getUpdates(@Context UriInfo uriInfo,
                             @QueryParam("from") String from,
                             @QueryParam("to") String to) {
    TicketService ticketService = getService(TicketService.class, null);
    String DATE_FORMAT = "dd-MM-yyyy";
    DateFormat df = new SimpleDateFormat(DATE_FORMAT);
    Calendar fromDate = Calendar.getInstance();
    Calendar toDate = Calendar.getInstance();
    try {
      fromDate.setTime(df.parse(from));
      toDate.setTime(df.parse(to));
    } catch (ParseException e) {
      LOG.error("Start and End Date format should be {}", DATE_FORMAT);
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    }
    TimeUnit timeUnit = TimeUnit.DAYS;
    long days = timeUnit.convert(toDate.getTime().getTime() - fromDate.getTime().getTime(), TimeUnit.MILLISECONDS);
    if (days > 7) {
      toDate.set(Calendar.DAY_OF_YEAR, fromDate.get(Calendar.DAY_OF_YEAR) + 7);
    }
    List<TicketDTO> ticketDTOs = ticketService.getTickets(fromDate, toDate);
    return Response.ok(buildJsonArray(ticketDTOs), MediaType.APPLICATION_JSON).cacheControl(cc).build();
  }

  /**
   * Gets the service.
   *
   * @param clazz         the class
   * @param containerName the container's name
   * @return the service
   */
  public static <T> T getService(Class<T> clazz, String containerName) {
    ExoContainer container = ExoContainerContext.getCurrentContainer();
    if (containerName != null) {
      container = RootContainer.getInstance().getPortalContainer(containerName);
    }
    if (container.getComponentInstanceOfType(clazz) == null) {
      containerName = PortalContainer.getCurrentPortalContainerName();
      container = RootContainer.getInstance().getPortalContainer(containerName);
    }
    return clazz.cast(container.getComponentInstanceOfType(clazz));
  }

  private JSONObject buildJsonObject(TicketDTO ticketDTO) {
    JSONObject ticket = new JSONObject();
    try {
      ticket.put("id", ticketDTO.getId());
      ticket.put("assignee", ticketDTO.getAssignee());
      ticket.put("description", ticketDTO.getDescription());
      ticket.put("endDate", ticketDTO.getEndDate());
      ticket.put("environmentName", ticketDTO.getEnvironmentName());
      ticket.put("infoType", ticketDTO.getInfoType() != null ? ticketDTO.getInfoType().name() : "");
      ticket.put("link", ticketDTO.getLink());
      ticket.put("severity", ticketDTO.getSeverity() != null ? ticketDTO.getSeverity().name() : "");
      ticket.put("spaceGroupId", ticketDTO.getSpaceGroupId());
      ticket.put("title", ticketDTO.getTitle());
      ticket.put("type", ticketDTO.getType() != null ? ticketDTO.getType().name() : "");
      ticket.put("startDate", ticketDTO.getStartDate());
      ticket.put("status", ticketDTO.getStatus());
      ticket.put("updateDate", ticketDTO.getUpdateDate());
    } catch (JSONException jsonException) {
      LOG.error("A problem when building JSON for ticket {}", ticketDTO.getId());
    }
    return ticket;
  }

  private String buildJsonArray(List<TicketDTO> ticketDTOS) {
    JSONArray array = new JSONArray();
    for (TicketDTO ticketDTO : ticketDTOS) {
      JSONObject ticket = buildJsonObject(ticketDTO);
      array.put(ticket);
    }
    return array.toString();
  }

}
