package org.exoplatform.cs.portlet.ticketMenu;

import juzu.*;
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.portlet.common.CSControllerBase;
import org.exoplatform.cs.service.CSSpaceService;
import org.exoplatform.cs.service.EnvironmentService;
import org.exoplatform.cs.service.TicketService;
import org.exoplatform.cs.service.tickets.Flow;
import org.exoplatform.cs.service.tickets.FlowState;
import org.exoplatform.cs.service.tickets.TicketStatusFlowService;
import org.exoplatform.cs.service.util.CSUtils;
import org.exoplatform.forum.service.ForumService;
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.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.MalformedURLException;
import java.net.URL;
import java.util.*;


public class TicketMenuController extends CSControllerBase {

  private static Log  LOG = ExoLogger.getLogger(TicketMenuController.class);
  private String     bundleString;
  ResourceBundle     bundle;
  private List<String> statusList = new ArrayList<String>();


    @Inject
  TicketService ticketService;


  @Inject
  TicketStatusFlowService ticketStatusFlowService;

  @Inject
  EnvironmentService environmentService;

  @Inject
  CSSpaceService spaceService;

    @Inject
    ForumService forumService;

    @Inject
    IdentityManager identityManager;


    @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 List<FlowState> getFlowStats(String name) {
    try {
      return ticketStatusFlowService.getFlowbyName(name).getStates();
    } catch (Exception e) {
      LOG.info("Flow  unfound");
    }
    return new ArrayList<FlowState>() ;
  }


  /**
   * this method returns the static list of ticket types
   *
   * @return
   */
  @Ajax
  @Resource(method = HttpMethod.GET )
  @MimeType.JSON
  @Jackson
  public List<String> getAllowedStates (String name) {
    try {
      String role = "customer";
      if(CSUtils.canManage()){
        role="support";
      }
      List<String> roles = new ArrayList<>();
      for (FlowState state : ticketStatusFlowService.getFlowbyName(name).getStates()){
        if(state.getRole().equals("any")||state.getRole().equals(role))
        roles.add(state.getState());
      }
      return roles;
    } catch (Exception e) {
      LOG.info("Flow  unfound");
    }
    return new ArrayList<>() ;
  }



  /**
     * this method returns the current ticket
     *
     * @return
     */
    @Ajax
    @Resource(method = HttpMethod.GET )
    @MimeType.JSON
    @Jackson
    public TicketDTO getTicket() {
        PortalRequestContext requestContext = Util.getPortalRequestContext();
        String uri=  requestContext.getRequest().getRequestURI();
        if(!uri.contains("/forum/topic/")) return null;
        String topicId =uri.split("/forum/topic/")[1].split("/")[0];
        TicketDTO ticketDTO =ticketService.findById(topicId);
/*        if(ticketDTO.getAttachedJira() != null){
          String data = getJSON("http://localhost/authmanager.php");
          AuthMsg msg = new Gson().fromJson(data, AuthMsg.class);
        }*/
/*        if (ticketDTO.getAssignee()!=null){
            Identity assigneeId = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, ticketDTO.getAssignee(), false);
            if(assigneeId!=null){
                Profile profile = assigneeId.getProfile();
                ticketDTO.setAssignee(profile.getFullName());
            }
        }*/
        return  ticketDTO;
    }

  /**
     * this method returns environment of the current ticket
     *
     * @return
     */
    @Ajax
    @Resource(method = HttpMethod.GET )
    @MimeType.JSON
    @Jackson
    public EnvironmentDTO getEnvironment(Long id) {
      try {
      return environmentService.getEnvironment(id);
    } catch (Exception e) {
    LOG.error("Error when updating ticket", e);
        return null;
  }

    }


  @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;
    }
  }


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

    /**
   * 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
  @Resource
  @MimeType.JSON
  @Jackson
  public Response getJiraDetails(String id) {
    try {
      String result = getJSON("https://jira.exoplatform.org/rest/api/latest/issue/"+id);
      if(result == null)return Response.status(401);
      return Response.ok(result);
    } catch (Throwable e) {
      LOG.error("error while getting jira", e);
      return Response.status(500);
    }
  }


  public String getJSON(String url) {
    HttpURLConnection c = null;
    try {
      URL u = new URL(url);
      c = (HttpURLConnection) u.openConnection();
      c.setRequestMethod("GET");
      c.setRequestProperty("Content-length", "0");
      c.setUseCaches(false);
      c.setAllowUserInteraction(false);

      c.connect();
      int status = c.getResponseCode();

      switch (status) {
        case 401: return null;
        case 200:
        case 201:
          BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
          StringBuilder sb = new StringBuilder();
          String line;
          while ((line = br.readLine()) != null) {
            sb.append(line+"\n");
          }
          br.close();
          return sb.toString();
      }

    } catch (Exception ex) {
      LOG.error("error");
    }  finally {
      if (c != null) {
        try {
          c.disconnect();
        } catch (Exception ex) {
          LOG.error("error");
        }
      }
    }
    return null;
  }

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

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

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

}
