package org.exoplatform.cs.rest.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.exoplatform.commons.file.model.FileItem;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.commons.utils.PropertyManager;
import org.exoplatform.cs.rest.model.CSpace;
import org.exoplatform.cs.rest.model.TicketAttachment;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
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.IdentityConstants;
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.exoplatform.social.core.space.spi.SpaceService;
import org.exoplatform.web.CacheUserProfileFilter;

public class CSRestUtils {
    private static final String SUPPORT_GROUP_NAME_CONFIGURATION = "exo.addon.cs.support.group.name";
    private static final String ADMINS_GROUP = "/platform/administrators";
    private static final Log LOG = ExoLogger.getLogger(CSRestUtils.class);

    public static User getCurrentUser() throws Exception {
        OrganizationService organizationService = CommonsUtils.getOrganizationService();
        if (ConversationState.getCurrent() == null || ConversationState.getCurrent().getIdentity() == null
                || ConversationState.getCurrent().getIdentity().getUserId() == null
                || ConversationState.getCurrent().getIdentity().getUserId().equals(IdentityConstants.SYSTEM)) {
            throw new IllegalStateException("Current user not found.");
        }
        User user = (User) ConversationState.getCurrent().getAttribute(CacheUserProfileFilter.USER_PROFILE);
        if (user == null) {
            String userId = ConversationState.getCurrent().getIdentity().getUserId();
            user = organizationService.getUserHandler().findUserByName(userId);
        }
        return user;
    }

    public static final Profile getProfile(String userName) throws Exception {
        IdentityManager identityManager = CommonsUtils.getService(IdentityManager.class);
        Identity identity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, userName);
        Profile profile = identity.getProfile();
        return profile;
    }

    public static String getSupportMemberGroupName() {
        String groupId = PropertyManager.getProperty(SUPPORT_GROUP_NAME_CONFIGURATION);
        if (groupId == null || groupId.isEmpty()) {
            groupId = "support-team";
        }
        return "/" + groupId;
    }

    public static List<User> getSupportMembers() {
        OrganizationService organizationService = CommonsUtils.getService(OrganizationService.class);
        String supportGroup = getSupportMemberGroupName();
        try {
            ListAccess<User> engSupportList = organizationService.getUserHandler().findUsersByGroupId(supportGroup);
            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 isSupportMember() {
        return ConversationState.getCurrent().getIdentity().isMemberOf(getSupportMemberGroupName());
    }

    public static CSpace extendCSSpace(CSpace cSpace) {
        SpaceService spaceService = CommonsUtils.getService(SpaceService.class);
        Space space = spaceService.getSpaceByGroupId(cSpace.getGroupId());
        cSpace.setAvatarUrl(space.getAvatarUrl());
        cSpace.setPrettyName(space.getPrettyName());
        return cSpace;
    }

    public static final boolean canManage() {
        return ConversationState.getCurrent().getIdentity().isMemberOf(ADMINS_GROUP)
                || isSupportMember();
    }

    public static final boolean authorizedOnCS(String spaceGroupId)  {
        SpaceService spaceService = CommonsUtils.getService(SpaceService.class);
        Space currCS = spaceService.getSpaceByGroupId(spaceGroupId);
        try {
            return spaceService.isMember(currCS, getCurrentUser().getUserName())
                    || spaceService.isSuperManager(getCurrentUser().getUserName());
        } catch (Exception e) {
            LOG.error("error while checking authorization on the customer space", e);
        }
        return false;
    }

    public static List<FileItem> getFiles(List<TicketAttachment> ticketAttachments) throws RepositoryException {
      List<FileItem> uploadedFile = new ArrayList<FileItem>();
      SessionProviderService sessionProviderService = CommonsUtils.getService(SessionProviderService.class);
      RepositoryService repositoryService = CommonsUtils.getService(RepositoryService.class);
      SessionProvider sessionProvider = sessionProviderService.getSystemSessionProvider(null);
      Session session = sessionProvider.getSession(
                                                   repositoryService.getCurrentRepository()
                                                                    .getConfiguration()
                                                                    .getDefaultWorkspaceName(),
                                                   repositoryService.getCurrentRepository());
      for (TicketAttachment ticketAttachment : ticketAttachments) {
        Node ticketAttachmentNode = session.getNodeByUUID(ticketAttachment.getId());
        Node ticketAttachmentResourceNode = ticketAttachmentNode.getNode("jcr:content");
        InputStream ticketAttachmentInputStream = ticketAttachmentResourceNode.getProperty("jcr:data").getStream();
        try {
          FileItem fileItem = new FileItem(null,
                                           ticketAttachmentNode.getProperty("exo:title").getString(),
                                           ticketAttachment.getMimetype(),
                                           "FORUM_ATTACHEMENTS_NAMESPACE",
                                           ticketAttachment.getSize(),
                                           new Date(),
                                           getCurrentUser().getUserName(),
                                           false,
                                           ticketAttachmentInputStream);
          uploadedFile.add(fileItem);
        } catch (Exception e) {
          LOG.error("error while creating file item", e);
        }
      }
      return uploadedFile;
    }

}
