package org.exoplatform.cs.service.util;

import org.exoplatform.agenda.model.AgendaUserSettings;
import org.exoplatform.agenda.service.AgendaUserSettingsService;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.commons.utils.PropertyManager;
import org.exoplatform.cs.listener.ForumListener;
import org.exoplatform.cs.service.tickets.TicketStatusFlowService;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.model.Page;
import org.exoplatform.portal.mop.page.PageContext;
import org.exoplatform.portal.mop.page.PageKey;
import org.exoplatform.portal.mop.page.PageService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.security.Identity;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
import org.exoplatform.social.core.manager.IdentityManager;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: ali
 * Date: 30/01/17
 * Time: 17:55
 */
public class CSUtils {
  private static final Log LOG = ExoLogger.getLogger(ForumListener.class);
  private static OrganizationService organizationService = CommonsUtils.getService(OrganizationService.class);


  private static final String SUPPORT_GROUP_NAME_CONFIGURATION = "exo.addon.cs.support.group.name";
  private static final String INTERNAL_SUPPORT_GROUP_ID_CONFIGURATION = "exo.addon.cs.internal.support.group.id";
  private static final String MANAGERS_GROUP_NAME_CONFIGURATION = "exo.addon.cs.managers.group.name";
  private static final String AUTO_ASSIGNEES_GROUP_NAME_CONFIGURATION = "exo.addon.cs.auto.assignee.group.name";

  public static List<User> getSupportMembers() {
    return getGroupMembers(getSupportTeamGroup());
  }

  public static List<User> getInternalSupportMembers() {
    String groupId = getInternalSupportTeamGroup();
    return groupId != null ? getGroupMembers(groupId) : null;
  }

  /**
   * Get the group ID for the support team
   * @return
   */
  public static String getSupportTeamGroup() {
    String groupId = PropertyManager.getProperty(SUPPORT_GROUP_NAME_CONFIGURATION);
    if (groupId == null || groupId.isEmpty()){
      groupId = "support-team";
    }
    return groupId;
  }

  public static String getInternalSupportTeamGroup() {
    String groupId = PropertyManager.getProperty(INTERNAL_SUPPORT_GROUP_ID_CONFIGURATION);
    if (groupId == null || groupId.isEmpty()){
      groupId = "/spaces/exo_support";
    }
    try {
      if ( organizationService.getGroupHandler().findGroupById(groupId) != null) {
        return groupId;
      }
    } catch(Exception e) {
      if( LOG.isDebugEnabled() ) {
        LOG.error("Group {} does not exist",groupId,e);
      }
    }
    return null;
  }


  public static List<User> getSupportManagers(){
    return getGroupMembers(getSupportManagersGroup());
  }

  public static List<User> getSupportAutoAssignees() {
    String groupId = PropertyManager.getProperty(AUTO_ASSIGNEES_GROUP_NAME_CONFIGURATION);
    if (groupId == null || groupId.isEmpty()){
      groupId = "support-assignee";
    }
    return getGroupMembers(groupId);
  }

  /**
   * Get the group ID for the support team
   * @return
   */
  public static String getSupportManagersGroup() {
    String groupId = PropertyManager.getProperty(MANAGERS_GROUP_NAME_CONFIGURATION);
    if (groupId == null || groupId.isEmpty()){
      groupId = "gss";
    }
    return groupId;
  }


  public static List<User> getGroupMembers(String groupId) {

    try {
      ListAccess<User> engSupportList = organizationService.getUserHandler().findUsersByGroupId(groupId);
      User[] users = engSupportList.load(0, engSupportList.getSize());
      return Arrays.asList(users);
    }
    catch (Exception e) {
      LOG.warn("Cannot get the list of group members");
      return new ArrayList<User>();
    }
  }

  public static boolean isMemberof(String user, String groupId) {
    OrganizationService organizationService = CommonsUtils.getService(OrganizationService.class);
    try {
      if(organizationService.getMembershipHandler().findMembershipsByUserAndGroup(user,groupId).size() > 0){
        return true;
      }
    } catch (Exception e) {
      LOG.error("Can not check the membership of {} in group {}", user, groupId, e);
      return false;
    }
    return false;
  }


  public static Boolean canManage() {
    Identity currentId = ConversationState.getCurrent().getIdentity();
    if(currentId.isMemberOf("/"+getSupportTeamGroup())||currentId.isMemberOf("/platform/administrators")) return true;
    return false;
  }

  public static Calendar getNextDate(Calendar c, long delay) {
    Calendar next = Calendar.getInstance();
    next.setTime(c.getTime());
    next.setTimeZone(TimeZone.getTimeZone("GMT+01"));
    next.setTimeInMillis(next.getTimeInMillis()+delay);
   while((next.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) || (next.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)){
     next.add(Calendar.DATE, 1);
   }
   return next;
  }


  public static long  getDiffBetweenTwoDates(Calendar c1, Calendar c2) {
    Calendar from=Calendar.getInstance();
    from.setTime(c1.getTime());
    Calendar to=Calendar.getInstance();
    to.setTime(c2.getTime());

    if((from.get(Calendar.HOUR_OF_DAY) > 18)){
      from.add(Calendar.DATE, 1);
      from.set(Calendar.HOUR_OF_DAY,9);
      from.set(Calendar.MINUTE,0);
    }
    if((from.get(Calendar.HOUR_OF_DAY) < 9)){
      from.set(Calendar.HOUR_OF_DAY,9);
      from.set(Calendar.MINUTE,0);
    }
    if((to.get(Calendar.HOUR_OF_DAY) > 18)){
      to.set(Calendar.HOUR_OF_DAY,18);
      to.set(Calendar.MINUTE,0);
    }
    if((to.get(Calendar.HOUR_OF_DAY) < 9)){
      to.add(Calendar.DATE, -1);
      to.set(Calendar.HOUR_OF_DAY,18);
      to.set(Calendar.MINUTE,0);
    }
    while((from.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) || (from.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)){
      from.add(Calendar.DATE, 1);
      from.set(Calendar.HOUR_OF_DAY,9);
      from.set(Calendar.MINUTE,0);
    }
    long diff = to.getTimeInMillis() - from.getTimeInMillis();
    while(from.before(to)){
      if(((from.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) || (from.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY))){
        diff-=24*60*60*1000;
      }
      from.add(Calendar.DATE, 1);
    }

    return ((diff<0) ? 0 : diff);
  }


  public static String formatDate(String date, TimeZone timezone) {
    if (date == null) {
      return null;
    }

    Calendar today = Calendar.getInstance(timezone);
    Calendar cal = Calendar.getInstance(timezone);
    cal.setTime(new Date(Long.parseLong(date)));
    String format = "MMM dd yyyy";
    if (cal.get(Calendar.YEAR) == today.get(Calendar.YEAR)) {
      format = "MMM dd";
    }
    SimpleDateFormat df = new SimpleDateFormat(format);
    df.setTimeZone(timezone);
    return df.format(cal.getTime());
  }

  public static TimeZone getUserTimezone(String username) {
    try {
      AgendaUserSettingsService agendaUserSettingsService =  CommonsUtils.getService(AgendaUserSettingsService.class);
      IdentityManager identityManager = CommonsUtils.getService(IdentityManager.class);
      org.exoplatform.social.core.identity.model.Identity user = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);
      AgendaUserSettings agendaUserSettings = agendaUserSettingsService.getAgendaUserSettings(Long.parseLong(user.getId()));
      return TimeZone.getTimeZone(agendaUserSettings.getTimeZoneId());
    } catch (Exception e) {
      LOG.error("Can't retrieve timezone", e);
    }
    return null;
  }

  public static String getDefaultState(String flow){
     TicketStatusFlowService ticketStatusFlowService = CommonsUtils.getService(TicketStatusFlowService.class);
    return  ticketStatusFlowService.getFlowbyName(flow).getDefaultState();
  }

  public static Page getPage(DataStorage dataStorage, PageService pageService, PageKey pageKey) throws Exception {
    PageContext pageContext = pageService.loadPage(pageKey);
    if (pageContext == null)
      return null;

    // PageService does not support the entire page at the moment, so we must
    // and update it with data page service does support.
    Page page = dataStorage.getPage(pageKey.format());
    pageContext.update(page);

    return page;
  }

}
