package org.exoplatform.platform.component;

import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.application.RequestNavigationData;
import org.exoplatform.portal.mop.user.UserNavigation;
import org.exoplatform.portal.mop.user.UserNode;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.social.core.space.SpaceUtils;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.space.spi.SpaceService;
import org.exoplatform.social.webui.Utils;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIComponent;
import org.exoplatform.webui.core.UIPortletApplication;
import org.exoplatform.webui.core.lifecycle.UIApplicationLifecycle;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
 * @author <a href="rtouzi@exoplatform.com">rtouzi</a>
 */
@ComponentConfig(lifecycle = UIApplicationLifecycle.class, template = "app:/groovy/platformNavigation/portlet/UISpaceNavigationPortlet/UISpaceNavigationPortlet.gtmpl",
        events = {
                @EventConfig(listeners = UISpaceNavigationPortlet.IncrementActionListener.class),
                @EventConfig(listeners = UISpaceNavigationPortlet.SelectSpaceActionListener.class)
        }
)
public class UISpaceNavigationPortlet extends UIPortletApplication {

    private static final Log LOG = ExoLogger.getLogger(UISpaceNavigationPortlet.class);

    private static final String MY_SPACE_REST_URL = "/space/user/searchSpace/";

    private static final String SPACE_URL_PATTERN = ":spaces";

    private SpaceService spaceService = null;

    private ListAccess<Space> spaceListAccess;

    private LinkedList<Space> spaceList = new LinkedList<Space>();

    private static final int MY_SPACES_MAX_NUMBER = 10;

    private static String portalContainerName = "";

    private int offset = 0;

    private boolean reload = false;

    private String oldNavigation = null;

    private String currentNavigation = null;

    private String selectedSpaceId = null;

    private String userId = null;

    public UISpaceNavigationPortlet() throws Exception {

        try {
            spaceService = ((SpaceService)getApplicationComponent(SpaceService.class));
            portalContainerName = PortalContainer.getCurrentPortalContainerName();
            if (spaceService != null) {
                this.spaceListAccess = spaceService.getLastAccessedSpace(getUserId(), null);
                setReload(true);
            }
            setOldNavigation(Util.getPortalRequestContext().getRequest().getRequestURI());

        } catch (Exception exception) {
            LOG.error("SpaceService could be 'null' when the Social profile isn't activated ", exception);
        }
    }

    /**
     *
     * @return
     */
    public List<Space> getSpaces() {
        Space space = Utils.getSpaceByContext();
        if (space != null) {
            putTop(space);
        }
        // Workaround to load only the 10 first space in the next iteration
        if (selectedSpaceId != null) {
            setSelectedSpaceId(null);
        }

        int from = 0;
        int to = this.offset + MY_SPACES_MAX_NUMBER;
        if (to >= this.spaceList.size()) {
            return this.spaceList;
        }
        return this.spaceList.subList(from, to);
    }

    /**
     * Refresh loaded spaces in left component UI
     * @throws Exception
     */
    public void refresh() throws Exception {
        setCurrentNavigation(Util.getPortalRequestContext().getRequest().getRequestURI());
        boolean navChanged = getCurrentNavigation().equals(getOldNavigation());
        if ((this.reload && selectedSpaceId == null) || !navChanged) {
            this.spaceList.clear();
            this.offset = 0;
            loadSpaces();
        }
        setOldNavigation(getCurrentNavigation());
    }

    /**
     * Complete the rendered Spaces list with the 10 next spaces
     * @throws Exception
     */
    private void loadSpaces() throws Exception {
        if (spaceListAccess != null) {
            this.spaceList.addAll(Arrays.asList(spaceListAccess.load(this.offset, MY_SPACES_MAX_NUMBER)));
        }
    }

    public Space putTop(String spaceId) {
        selectedSpaceId = spaceId;
        Space space = new Space();
        space.setId(spaceId);
        return putTop(space);
    }

    private Space putTop(Space space) {
        int idx = this.spaceList.indexOf(space);
        Space got = null;
        if (idx >= 0) {
            got = this.spaceList.remove(idx);
        } else {
            got = Utils.getSpaceService().getSpaceById(space.getId());
        }
        this.spaceList.addFirst(got);
        return got;
    }

    public int numberOfRemainSpaces() throws Exception {
        if (spaceListAccess != null) {
            int to = this.offset + MY_SPACES_MAX_NUMBER;
            int newLimit = Math.min(to, this.spaceList.size());
            return spaceListAccess.getSize() - newLimit;
        }
        return 0;
    }

    private String getUserId()
    {
        if (userId == null) {
            userId = Util.getPortalRequestContext().getRemoteUser();
        }
        return userId;
    }

    /**
     * Builds the Space URI
     * @param space
     * @return
     * @throws Exception
     */
    public String buildSpaceURL(Space space) throws Exception
    {
        return Utils.getSpaceHomeURL(space);
    }
    public Boolean isSelectedSpace(Space space) throws Exception {
        String groupId = Util.getPortalRequestContext().getControllerContext().getParameter(RequestNavigationData.REQUEST_SITE_NAME);
        return space.getGroupId().equalsIgnoreCase(groupId);
    }


    public static class SelectSpaceActionListener extends EventListener<UISpaceNavigationPortlet>
    {
        public void execute(Event<UISpaceNavigationPortlet> event) throws Exception {
            PortalRequestContext pContext = Util.getPortalRequestContext();
            UISpaceNavigationPortlet uisource = (UISpaceNavigationPortlet) event.getSource();
            String spaceId = event.getRequestContext().getRequestParameter(UIComponent.OBJECTID);
            Space space = uisource.putTop(spaceId);
            //--- Get the space URL using reouter API
            String spaceURL = Utils.getSpaceHomeURL(space);
            //---- Get only the GROUP navigation
            if (spaceURL.contains(portalContainerName)) {
                spaceURL = spaceURL.substring(portalContainerName.length()+2);
            }
            
            String fullUrl = ((HttpServletRequest) pContext.getRequest()).getRequestURL().toString();
            String subUrl = StringUtils.substringBefore(fullUrl,Util.getPortalRequestContext().getRequest().getRequestURI());
            subUrl +="/"+ portalContainerName;
            String applicationDisplayed = "";
            String constructURL = fullUrl.substring(subUrl.length()+1);
            subUrl =new StringBuffer(subUrl).append("/").append(spaceURL).toString();
            if (fullUrl.contains(SPACE_URL_PATTERN)) {
                int count = StringUtils.countMatches(constructURL, "/");
                
                if(count != 2){
                  applicationDisplayed = constructURL.substring(constructURL.lastIndexOf("/") + 1);
                  String selectedAppNodeName = uisource.checkAndGetExistingAppNodeName(space, applicationDisplayed); 
                  if (selectedAppNodeName != null)
                    subUrl =new StringBuffer(subUrl).append("/").append(selectedAppNodeName).toString();
                }
            }

            uisource.setReload(true);
            event.getRequestContext().getJavascriptManager().getRequireJS().require("SHARED/navigation-spaces-search", "spaceSearchNavigationPortlet").addScripts("spaceSearchNavigationPortlet.ajaxRedirect('"+subUrl+"');");
        }
    }

    public static class IncrementActionListener extends EventListener<UISpaceNavigationPortlet>
    {
        public void execute(Event<UISpaceNavigationPortlet> event)
                throws Exception
        {
            HttpServletRequest request = Util.getPortalRequestContext().getRequest();

            UISpaceNavigationPortlet uisource = (UISpaceNavigationPortlet) event.getSource();

            uisource.loadMore(MY_SPACES_MAX_NUMBER);

            uisource.setReload(false);

            event.getRequestContext().addUIComponentToUpdateByAjax(uisource);
        }
    }   

    protected String getRestUrl() {
        return getCurrentRestURL().concat(MY_SPACE_REST_URL);
    }

    public static String getCurrentRestURL() {
        StringBuilder sb = new StringBuilder();
        sb.append("/").append(PortalContainer.getCurrentPortalContainerName()).append("/");
        sb.append(PortalContainer.getCurrentRestContextName());
        return sb.toString();
    }

    public void loadMore(int capacity) throws Exception {
        this.offset += capacity;
        loadSpaces();
    }

    public void setReload(boolean reload) {
        this.reload = reload;
    }
    public void setSelectedSpaceId(String selectedSpaceId) {
        this.selectedSpaceId = selectedSpaceId;
    }
    public String getCurrentNavigation() {
        return currentNavigation;
    }

    public void setCurrentNavigation(String currentNavigation) {
        this.currentNavigation = currentNavigation;
    }

    public String getOldNavigation() {
        return oldNavigation;
    }

    public void setOldNavigation(String oldNavigation) {
        this.oldNavigation = oldNavigation;
    }
    
    private String checkAndGetExistingAppNodeName(Space space, String appId) throws Exception {
      if (appId == null) return null;
      String groupId = space.getGroupId();
      UserNavigation userNav = SpaceUtils.getGroupNavigation(groupId);
      UserNode homeNode = SpaceUtils.getHomeNodeWithChildren(userNav, space.getUrl());
      for (UserNode node : homeNode.getChildren()) {
        if (appId.equals(node.getName())) return appId;
      }
      
      // in case application name has been changed
      String leftSpaceGroupId = Util.getPortalRequestContext()
          .getControllerContext().getParameter(RequestNavigationData.REQUEST_SITE_NAME);
      Space leftSpace = spaceService.getSpaceByGroupId(leftSpaceGroupId);
      String[] leftSpaceApps = leftSpace.getApp().split(",");
      String selectedAppId = ""; 
      for (String app : leftSpaceApps) {
        if (app.contains(appId.replace("_", " "))) {
          selectedAppId = app.split(":")[0];
          break;
        }
      }
      
      if (selectedAppId.isEmpty()) return null;
      
      String[] spaceApps = space.getApp().split(",");
      for (String spaceApp : spaceApps) {
        if (spaceApp.contains(selectedAppId)) return spaceApp.split(":")[1].replace(" ", "_");
      }
      
      return null;
    }
}
