package org.exoplatform.cs.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.gatein.api.Portal;
import org.gatein.api.PortalRequest;
import org.gatein.api.navigation.Navigation;
import org.gatein.api.navigation.Node;
import org.gatein.api.navigation.NodePath;
import org.gatein.api.navigation.Nodes;
import org.gatein.api.security.Group;
import org.gatein.api.site.Site;
import org.gatein.api.site.SiteId;

import org.exoplatform.cs.service.util.SpacePageUtils;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.ModelObject;
import org.exoplatform.portal.config.model.Page;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.SiteKey;
import org.exoplatform.portal.mop.management.operations.page.PageUtils;
import org.exoplatform.portal.mop.page.PageKey;
import org.exoplatform.portal.mop.page.PageService;
import org.exoplatform.social.core.space.SpaceApplicationConfigPlugin;
import org.exoplatform.social.core.space.SpaceApplicationConfigPlugin.SpaceApplication;
import org.exoplatform.social.core.space.SpaceException;
import org.exoplatform.social.core.space.impl.DefaultSpaceApplicationHandler;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.space.spi.SpaceService;

public class CSSpaceApplicationHandler extends DefaultSpaceApplicationHandler {
  private static final String          CS_PARENT_NAV_NAME = "cs";

  public static final String           NAME               = "CSSpace";

  private UserPortalConfigService      portalConfigService;

  private SpaceApplicationConfigPlugin spaceApplicationConfigPlugin;

  private SpaceService                 spaceService;

  public CSSpaceApplicationHandler(SpaceService spaceService,
                                   DataStorage dataStorage,
                                   PageService pageService,
                                   UserPortalConfigService portalConfigService) {
    super(dataStorage, pageService);
    this.portalConfigService = portalConfigService;
    this.spaceService = spaceService;
  }

  @Override
  public void initApps(Space space, SpaceApplicationConfigPlugin spaceApplicationConfigPlugin) throws SpaceException {
    try {
      if (this.spaceApplicationConfigPlugin == null) {
        throw new IllegalStateException("CS Space config is null");
      }
      // Initialize space with home page only
      super.initApps(space, this.spaceApplicationConfigPlugin);

      createSpecificSiteLayoutAndNav(space);

      // Get default application list
      List<SpaceApplication> spaceApplications = spaceService.getSpaceApplicationConfigPlugin().getSpaceApplicationList();
      for (SpaceApplication spaceApplication : spaceApplications) {
        spaceService.installApplication(space, spaceApplication.getPortletName());
      }
    } catch (Exception e) {
      throw new SpaceException(SpaceException.Code.UNABLE_TO_CREAT_NAV, e);
    }
  }

  public void setSpaceApplicationConfigPlugin(SpaceApplicationConfigPlugin spaceApplicationConfigPlugin) {
    this.spaceApplicationConfigPlugin = spaceApplicationConfigPlugin;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String getName() {
    return NAME;
  }

  private void createSpecificSiteLayoutAndNav(Space space) throws Exception {
    // Create specific pages & navigations
    portalConfigService.createUserPortalConfig(PortalConfig.GROUP_TYPE, space.getGroupId(), "CSSpace");

    // Move specific navigations under original home page of space
    SiteKey siteKey = SiteKey.group(space.getGroupId());
    PortalRequest portalRequest = PortalRequest.getInstance();
    if (portalRequest == null) {
      return;
    }
    Portal portal = portalRequest.getPortal();
    Group group = new Group(space.getGroupId());
    Site groupSpace = portal.getSite(new SiteId(group));
    Navigation navigation = portal.getNavigation(groupSpace.getId());
    Node home = navigation.getNode(NodePath.path(space.getUrl()), Nodes.visitAll());
    Node tempHome = navigation.getNode(NodePath.path(CS_PARENT_NAV_NAME), Nodes.visitAll());
    Iterator<Node> nodeIterator = tempHome.iterator();
    while (nodeIterator.hasNext()) {
      Node childNode = (Node) nodeIterator.next();
      Node newNode = home.addChild(childNode.getName());
      newNode.setIconName(childNode.getIconName());
      newNode.setPageId(childNode.getPageId());
      newNode.setVisibility(childNode.getVisibility());
      navigation.saveNode(home);
      navigation.removeNode(childNode.getNodePath());

      // Convert Portlet preferences
      convertChildApplicationPreferences(space, siteKey, newNode);
    }
    // Set home page
    home.setPageId(tempHome.getPageId());
    navigation.saveNode(home);
    // Convert Portlet preferences

    convertChildApplicationPreferences(space, siteKey, home);

    // Remove temporary home navigation page
    navigation.removeNode(tempHome.getNodePath());
  }

  private void convertChildApplicationPreferences(Space space, SiteKey siteKey, Node newNode) throws Exception {
    PageKey pageKey = new PageKey(siteKey, newNode.getPageId().getPageName());
    Page newPage = PageUtils.getPage(portalConfigService.getDataStorage(), portalConfigService.getPageService(), pageKey);
    ArrayList<ModelObject> modelObjects = newPage.getChildren();
    SpacePageUtils.convert(modelObjects, space.getGroupId());
  }

}
