package org.exoplatform.cs.service.listener;

import java.util.Calendar;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;


import org.exoplatform.commons.api.notification.NotificationContext;
import org.exoplatform.commons.api.notification.model.PluginKey;
import org.exoplatform.commons.notification.impl.NotificationContextImpl;
import org.exoplatform.cs.dao.LogDAO;
import org.exoplatform.cs.dto.LogType;
import org.exoplatform.cs.entity.LogEntity;
import org.exoplatform.cs.entity.TopicEntity;
import org.exoplatform.cs.integration.notification.CSStatusChangedNotificationPlugin;
import org.exoplatform.cs.integration.notification.CSTicketAssignedNotificationPlugin;
import org.exoplatform.cs.integration.notification.CSTicketAssignedToMeNotificationPlugin;
import org.exoplatform.cs.integration.notification.CSTicketClosedNotificationPlugin;
import org.exoplatform.cs.service.CSConstants;
import org.exoplatform.cs.service.util.ForumUtils;
import org.exoplatform.forum.service.*;
import org.exoplatform.services.listener.Asynchronous;
import org.exoplatform.services.listener.Event;
import org.exoplatform.services.listener.Listener;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.resources.ResourceBundleService;

import static org.exoplatform.cs.service.CSConstants.STATUS_CLOSED;

/**
 * Created by IntelliJ IDEA.
 * User: ali
 * Date: 09/01/17
 * Time: 15:17
 */

@Asynchronous
public class TicketUpdatedLogListener extends Listener<TopicEntity, Map<String,String>> {
  private static final Log LOG = ExoLogger.getLogger(TicketUpdatedLogListener.class);
  private static final String STATUS_RB = "cs.ticket.status.";
  private static final String TICKET_STATUS_UPDATED_MESSAGE = "cs.ticket.status.updated";
  private static final String TICKET_TYPE_UPDATED_MESSAGE = "cs.ticket.type.updated";
  private static final String TICKET_SEVERITY_UPDATED_MESSAGE = "cs.ticket.severity.updated";
  private static final String TYPE_RB = "cs.ticket.type.";
  private static final String SEVERITY_RB = "cs.ticket.severity.";
  private static final String TICKET_ASSIGNED_MESSAGE_KEY = "cs.ticket.assigned.message";
  private LogDAO logDAO;
  private ForumService forumService;
  private ResourceBundleService resourceBundleService;

  public TicketUpdatedLogListener(LogDAO logDAO,ForumService forumService,ResourceBundleService resourceBundleService) {
    this.logDAO = logDAO;
    this.forumService = forumService;
    this.resourceBundleService = resourceBundleService;
  }

  @Override
  public void onEvent(Event<TopicEntity, Map<String, String>> event) throws Exception {

    ResourceBundle resourceBundle = resourceBundleService.getResourceBundle("locale.customer-space", Locale.getDefault());
    TopicEntity ticket = event.getSource();
    Map<String,String> data = event.getData();
    String userID = data.get(CSConstants.USERID);
    Calendar now = Calendar.getInstance();
    //StringBuilder sb = new StringBuilder();

    String oldAssignee = data.get(CSConstants.OLD_ASSIGNEE);
    String newAssignee = data.get(CSConstants.NEW_ASSIGNEE);
    if(newAssignee != null){
      LOG.info("Assignee changed from {} to {}", oldAssignee, newAssignee);
      LogEntity logEntity = new LogEntity(LogType.TICKET_ASSIGNEE_CHANGED, userID, now,oldAssignee,newAssignee,ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);

      NotificationContext ctx = NotificationContextImpl.cloneInstance().append(CSTicketAssignedNotificationPlugin.TICKET, ticket).append(CSTicketAssignedToMeNotificationPlugin.LOG_ENTITY, logEntity);
      ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(CSTicketAssignedNotificationPlugin.ID))).execute(ctx);


/*      NotificationContext mctx = NotificationContextImpl.cloneInstance().append(CSTicketAssignedToMeNotificationPlugin.TICKET, ticket).append(CSTicketAssignedToMeNotificationPlugin.LOG_ENTITY, logEntity);
      mctx.getNotificationExecutor().with(mctx.makeCommand(PluginKey.key(CSTicketAssignedToMeNotificationPlugin.ID))).execute(mctx);*/
    }

    String oldType = data.get(CSConstants.OLD_TYPE);
    String newType = data.get(CSConstants.NEW_TYPE);
    if(oldType != null && newType != null){
      LOG.info("Type changed from {} to {}", oldType, newType);
      LogEntity logEntity = new LogEntity(LogType.TICKET_TYPE_CHANGED, userID, now,oldType,newType,ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);
      //sb.append(replaceVarsInBundle(resourceBundle.getString(TICKET_TYPE_UPDATED_MESSAGE),resourceBundle.getString(TYPE_RB+oldType),resourceBundle.getString(TYPE_RB+newType)));
    }
    String oldSeverity = data.get(CSConstants.OLD_SEVERITY);
    String newSeverity = data.get(CSConstants.NEW_SEVERITY);
    if(oldSeverity != null && newSeverity != null){
      LOG.info("Severity changed from {} to {}", oldSeverity, newSeverity);
      LogEntity logEntity = new LogEntity(LogType.TICKET_SEVERITY_CHANGED, userID, now,oldSeverity,newSeverity,ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);

      //sb.append(replaceVarsInBundle(resourceBundle.getString(TICKET_SEVERITY_UPDATED_MESSAGE),resourceBundle.getString(SEVERITY_RB+oldSeverity),resourceBundle.getString(SEVERITY_RB+newSeverity)));
    }
    String oldStatus = data.get(CSConstants.OLD_STATUS);
    String newStatus = data.get(CSConstants.NEW_STATUS);
    if(oldStatus != null && newStatus != null){
      LOG.info("Status changed from {} to {}", oldStatus, newStatus);
      LogEntity logEntity = new LogEntity(LogType.TICKET_STATUS_CHANGED, userID, now, oldStatus, newStatus, ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);
      //sb.append(replaceVarsInBundle(resourceBundle.getString(TICKET_STATUS_UPDATED_MESSAGE),resourceBundle.getString(STATUS_RB+oldStatus),resourceBundle.getString(STATUS_RB+newStatus)));
      //if ticket is closed, close the topic too
      if (STATUS_CLOSED.equalsIgnoreCase(newStatus)){
        Topic topic = ForumUtils.getTopicByTicket(forumService,ticket);
        topic.setTopicName(CSConstants.RESOLVED_TAG + topic.getTopicName());
          topic.setModifiedBy(data.get(CSConstants.USERID));
          //topic.setIsClosed(true);
        forumService.saveTopic(topic.getCategoryId(),topic.getForumId(),topic,false,false,new MessageBuilder());

        NotificationContext ctx = NotificationContextImpl.cloneInstance().append(CSTicketClosedNotificationPlugin.TICKET, ticket).append(CSTicketAssignedToMeNotificationPlugin.LOG_ENTITY, logEntity);
        ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(CSTicketClosedNotificationPlugin.ID))).execute(ctx);

      }
      //if ticket is reopened, reopen the topic too
      if (STATUS_CLOSED.equalsIgnoreCase(oldStatus)){
        Topic topic = ForumUtils.getTopicByTicket(forumService,ticket);
        topic.setTopicName(topic.getTopicName().replace(CSConstants.RESOLVED_TAG,""));
        topic.setModifiedBy(data.get(CSConstants.USERID));
        //topic.setIsClosed(false);
        forumService.saveTopic(topic.getCategoryId(),topic.getForumId(),topic,false,false,new MessageBuilder());
      }


      NotificationContext ctx = NotificationContextImpl.cloneInstance().append(CSStatusChangedNotificationPlugin.TICKET, ticket).append(CSTicketAssignedToMeNotificationPlugin.LOG_ENTITY, logEntity);
      ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(CSStatusChangedNotificationPlugin.ID))).execute(ctx);

    }

    // if time to first response set
    String timeToFirstResponse = data.get(CSConstants.TIME_TO_FIRST_RESPONSE);
    if(timeToFirstResponse!=null){
      LOG.info("TimeToFirstResponse set to {} ", Long.parseLong(timeToFirstResponse));
      LogEntity logEntity = new LogEntity(LogType.TIME_TO_FIRST_RESPONSE_ADDED, userID, now, "","" , ticket,Long.parseLong(timeToFirstResponse),null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);
    }


    // if time to resolution set
    String timeToResolution = data.get(CSConstants.TIME_TO_RESOLUTION);
    if(timeToResolution!=null){
      LOG.info("TimeToResolution set to {} ", Long.parseLong(timeToResolution));
      LogEntity logEntity = new LogEntity(LogType.TIME_TO_RESOLUTION_ADDED, userID, now, "","" , ticket,null,Long.parseLong(timeToResolution),ticket.getSpace().getGroupId());
      logDAO.create(logEntity);
    }

    // if user satisfaction set
    String userSatisfaction = data.get(CSConstants.NEW_CUSTOMER_SATISFACTION);
    if(userSatisfaction!=null){
      LogEntity logEntity = new LogEntity(LogType.CUSTOMER_SATISFACTION_ADDED, userID, now, "", userSatisfaction, ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);
    }

    // if Owner changed
    String oldOwner = data.get(CSConstants.OLD_OWNER);
    String newOwner = data.get(CSConstants.NEW_OWNER);
    if(oldOwner != null && newSeverity != null){
      LOG.info("Owner changed from {} to {}", oldOwner, newOwner);
      LogEntity logEntity = new LogEntity(LogType.TICKET_OWNER_CHANGED, userID, now,oldOwner,newOwner,ticket,null,null,ticket.getSpace().getGroupId());
      logDAO.create(logEntity);

      //sb.append(replaceVarsInBundle(resourceBundle.getString(TICKET_SEVERITY_UPDATED_MESSAGE),resourceBundle.getString(SEVERITY_RB+oldSeverity),resourceBundle.getString(SEVERITY_RB+newSeverity)));
    }
//    if(!sb.toString().isEmpty()){
//      ForumUtils.postMessageToTicket(forumService, ticket,sb.toString());
//    }

    if (oldStatus != null && newStatus != null && ticket.getAssignee() != null && oldStatus.equals(CSConstants.STATUS_NEW) && (newStatus.equals(CSConstants.STATUS_OPEN) || newStatus.equals(CSConstants.STATUS_INPROGRESS))) {
      String language = ticket.getSpace().getLanguage();
      String message = resourceBundleService.getResourceBundle("locale.customer-space", new Locale(language)).getString(TICKET_ASSIGNED_MESSAGE_KEY);
      ForumUtils.postMessageToTicket(forumService, ticket, message);
    }


  }

  private String replaceVarsInBundle(String bundle, String... strings){
    for(int i=0;i<strings.length;i++){
      bundle = bundle.replace("{"+i+"}",strings[i]);
    }
    return bundle;
  }
}
