/*
 * Copyright (C) 2003-2009 eXo Platform SAS.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see<http://www.gnu.org/licenses/>.
 */
package org.exoplatform.wcm.webui.category.config;

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

import javax.jcr.Node;
import javax.portlet.PortletMode;
import javax.portlet.PortletPreferences;

import org.exoplatform.ecm.webui.selector.UISelectable;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.webui.portal.UIPortal;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.cms.taxonomy.TaxonomyService;
import org.exoplatform.services.cms.views.ApplicationTemplateManagerService;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.config.RepositoryEntry;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.wcm.portal.LivePortalManagerService;
import org.exoplatform.wcm.webui.Utils;
import org.exoplatform.wcm.webui.category.UICategoryNavigationConstant;
import org.exoplatform.wcm.webui.category.UICategoryNavigationPortlet;
import org.exoplatform.wcm.webui.category.UICategoryNavigationUtils;
import org.exoplatform.wcm.webui.selector.page.UIPageSelector;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.webui.application.portlet.PortletRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIPopupContainer;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.core.model.SelectItemOption;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormSelectBox;
import org.exoplatform.webui.form.UIFormStringInput;
import org.exoplatform.webui.form.ext.UIFormInputSetWithAction;

/**
 * Created by The eXo Platform SAS
 * Author : eXoPlatform
 * chuong.phan@exoplatform.com, phan.le.thanh.chuong@gmail.com
 * Jun 28, 2009
 */
@ComponentConfig(
    lifecycle = UIFormLifecycle.class,
    template = "system:/groovy/webui/form/UIForm.gtmpl",
    events = {
        @EventConfig(listeners = UICategoryNavigationConfig.SaveActionListener.class),
        @EventConfig(listeners = UICategoryNavigationConfig.CancelActionListener.class),
        @EventConfig(listeners = UICategoryNavigationConfig.ChangeRepositoryActionListener.class),
        @EventConfig(listeners = UICategoryNavigationConfig.SelectTargetPathActionListener.class)
    }
)
public class UICategoryNavigationConfig extends UIForm implements UISelectable {

  /** The popup id. */
  private String popupId;
  
  /**
   * Instantiates a new uI category navigation config.
   * 
   * @throws Exception the exception
   */
  public UICategoryNavigationConfig() throws Exception {
    PortletPreferences preferences = UICategoryNavigationUtils.getPortletPreferences();

    String preferenceRepository = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_REPOSITORY, "");
    RepositoryService repositoryService = getApplicationComponent(RepositoryService.class) ;  
    List<SelectItemOption<String>> repositories = new ArrayList<SelectItemOption<String>>() ;
    for(RepositoryEntry repositoryEntry : repositoryService.getConfig().getRepositoryConfigurations()) {
      repositories.add(new SelectItemOption<String>(repositoryEntry.getName())) ;
    }
    UIFormSelectBox repositoryFormSelectBox = new UIFormSelectBox(UICategoryNavigationConstant.REPOSITORY_FORM_SELECTBOX, UICategoryNavigationConstant.REPOSITORY_FORM_SELECTBOX, repositories);
    repositoryFormSelectBox.setValue(preferenceRepository);
    repositoryFormSelectBox.setOnChange("ChangeRepository");
    addUIFormInput(repositoryFormSelectBox);
    
    String preferenceTreeTitle = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_TITLE, "");
    addUIFormInput(new UIFormStringInput(UICategoryNavigationConstant.TREE_TITLE_FORM_STRING_INPUT, UICategoryNavigationConstant.TREE_TITLE_FORM_STRING_INPUT, preferenceTreeTitle));
    
    String preferenceTreeName = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, "");
    List<SelectItemOption<String>> trees = getTaxonomyTrees(preferenceRepository);
    UIFormSelectBox treeNameFormSelectBox = new UIFormSelectBox(UICategoryNavigationConstant.TREE_NAME_FORM_SELECTBOX, UICategoryNavigationConstant.TREE_NAME_FORM_SELECTBOX, trees);
    treeNameFormSelectBox.setValue(preferenceTreeName);
    addUIFormInput(treeNameFormSelectBox);
    
    String preferencePortletName = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_PORTLET_NAME, "");
    String preferenceTemplateCategory = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_TEMPLATE_CATEGORY, "");
    String preferenceTemplatePath = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_TEMPLATE_PATH, "");
    List<SelectItemOption<String>> templates = getTemplateList(preferencePortletName, preferenceTemplateCategory);
    UIFormSelectBox templateFormSelectBox = new UIFormSelectBox(UICategoryNavigationConstant.TEMPLATE_FORM_SELECTBOX, UICategoryNavigationConstant.TEMPLATE_FORM_SELECTBOX, templates);
    templateFormSelectBox.setValue(preferenceTemplatePath);
    addUIFormInput(templateFormSelectBox);
    
    String preferenceTargetPath = preferences.getValue(UICategoryNavigationConstant.PREFERENCE_TARGET_PAGE, "");
    UIFormInputSetWithAction targetPathFormInputSet = new UIFormInputSetWithAction(UICategoryNavigationConstant.TARGET_PATH_FORM_INPUT_SET);
    UIFormStringInput targetPathFormStringInput = new UIFormStringInput(UICategoryNavigationConstant.TARGET_PATH_FORM_STRING_INPUT, UICategoryNavigationConstant.TARGET_PATH_FORM_STRING_INPUT, preferenceTargetPath);
    targetPathFormStringInput.setEditable(false);
    targetPathFormInputSet.setActionInfo(UICategoryNavigationConstant.TARGET_PATH_FORM_STRING_INPUT, new String[] {"SelectTargetPath"}) ;
    targetPathFormInputSet.addUIFormInput(targetPathFormStringInput);
    addChild(targetPathFormInputSet);
    
    setActions(new String[] {"Save", "Cancel"});
  }
  
  /**
   * Gets the popup id.
   * 
   * @return the popup id
   */
  public String getPopupId() {
    return popupId;
  }

  /**
   * Sets the popup id.
   * 
   * @param popupId the new popup id
   */
  public void setPopupId(String popupId) {
    this.popupId = popupId;
  }

  /**
   * Gets the template list.
   * 
   * @param portletName the portlet name
   * @param templateCategory the template category
   * 
   * @return the template list
   * 
   * @throws Exception the exception
   */
  private List<SelectItemOption<String>> getTemplateList(String portletName, String templateCategory) throws Exception {
    List<SelectItemOption<String>> templates = new ArrayList<SelectItemOption<String>>();
    RepositoryService repositoryService = getApplicationComponent(RepositoryService.class);
    ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
    ApplicationTemplateManagerService applicationTemplateManagerService = getApplicationComponent(ApplicationTemplateManagerService.class);
    String repository = manageableRepository.getConfiguration().getName();
    List<Node> templateNodes = applicationTemplateManagerService.getTemplatesByCategory(
                                                                                        repository,
                                                                                        portletName,
                                                                                        templateCategory,
                                                                                        Utils.getSessionProvider());
    for (Node templateNode : templateNodes) {
      String templateName = templateNode.getName();
      String templatePath = templateNode.getPath();
      templates.add(new SelectItemOption<String>(templateName, templatePath));
    }
    return templates;
  }
  
  /**
   * Gets the taxonomy trees.
   * 
   * @param repository the repository
   * 
   * @return the taxonomy trees
   * 
   * @throws Exception the exception
   */
  private List<SelectItemOption<String>> getTaxonomyTrees(String repository) throws Exception {
    TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
    LivePortalManagerService livePortalManagerService = getApplicationComponent(LivePortalManagerService.class);
    List<Node> taxonomyNodes = taxonomyService.getAllTaxonomyTrees(repository);
    List<SelectItemOption<String>> taxonomyTrees = new ArrayList<SelectItemOption<String>>();
    for(Node taxonomyNode : taxonomyNodes) {
    	Node portalNode = livePortalManagerService.getLivePortalByChild(taxonomyNode);
    	if (portalNode != null)
    		taxonomyTrees.add(new SelectItemOption<String>(taxonomyNode.getName(), taxonomyNode.getName()));
    }
    return taxonomyTrees;
  }
  
  /* (non-Javadoc)
   * @see org.exoplatform.ecm.webui.selector.UISelectable#doSelect(java.lang.String, java.lang.Object)
   */
  public void doSelect(String selectField, Object value) throws Exception {
    UIFormStringInput formStringInput = findComponentById(selectField);
    formStringInput.setValue(value.toString()) ;
    
    UICategoryNavigationPortlet categoryNavigationPortlet = getAncestorOfType(UICategoryNavigationPortlet.class);
    UIPopupContainer popupContainer = categoryNavigationPortlet.getChild(UIPopupContainer.class);
    Utils.closePopupWindow(popupContainer, popupId);
  }
  
  /**
   * The listener interface for receiving saveAction events.
   * The class that is interested in processing a saveAction
   * event implements this interface, and the object created
   * with that class is registered with a component using the
   * component's <code>addSaveActionListener<code> method. When
   * the saveAction event occurs, that object's appropriate
   * method is invoked.
   * 
   * @see SaveActionEvent
   */
  public static class SaveActionListener extends EventListener<UICategoryNavigationConfig> {
    
    /* (non-Javadoc)
     * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
     */
    public void execute(Event<UICategoryNavigationConfig> event) throws Exception {
      UICategoryNavigationConfig categoryNavigationConfig = event.getSource();
      String preferenceRepository = categoryNavigationConfig.getUIFormSelectBox(UICategoryNavigationConstant.REPOSITORY_FORM_SELECTBOX).getValue();
      String preferenceTreeName = categoryNavigationConfig.getUIFormSelectBox(UICategoryNavigationConstant.TREE_NAME_FORM_SELECTBOX).getValue();
      String preferenceTreeTitle = categoryNavigationConfig.getUIStringInput(UICategoryNavigationConstant.TREE_TITLE_FORM_STRING_INPUT).getValue();
      if (preferenceTreeTitle == null) preferenceTreeTitle = "";
      String preferenceTargetPath = categoryNavigationConfig.getUIStringInput(UICategoryNavigationConstant.TARGET_PATH_FORM_STRING_INPUT).getValue();
      String preferenceTemplate = categoryNavigationConfig.getUIFormSelectBox(UICategoryNavigationConstant.TEMPLATE_FORM_SELECTBOX).getValue();
      PortletPreferences portletPreferences = UICategoryNavigationUtils.getPortletPreferences();
      portletPreferences.setValue(UICategoryNavigationConstant.PREFERENCE_REPOSITORY, preferenceRepository);
      portletPreferences.setValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, preferenceTreeName);
      portletPreferences.setValue(UICategoryNavigationConstant.PREFERENCE_TREE_TITLE, preferenceTreeTitle);
      portletPreferences.setValue(UICategoryNavigationConstant.PREFERENCE_TARGET_PAGE, preferenceTargetPath);
      portletPreferences.setValue(UICategoryNavigationConstant.PREFERENCE_TEMPLATE_PATH, preferenceTemplate);
      portletPreferences.store();

      if (!Utils.isEditPortletInCreatePageWizard()) { 
        PortalRequestContext portalRequestContext = Util.getPortalRequestContext();
        UIPortal uiPortal = Util.getUIPortal();
        
        String pageNodeSelected = uiPortal.getSelectedNode().getName();
        String portalURI = portalRequestContext.getPortalURI();

        ((PortletRequestContext)event.getRequestContext()).setApplicationMode(PortletMode.VIEW);
        Utils.closePopupWindow(categoryNavigationConfig, UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW);
        event.getRequestContext().getJavascriptManager().addJavascript("ajaxRedirect('" + portalURI + pageNodeSelected + "');");
      } else {
        if (Utils.isQuickEditMode(categoryNavigationConfig, UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW)) {
          Utils.closePopupWindow(categoryNavigationConfig, UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW);
        } else {
          Utils.createPopupMessage(categoryNavigationConfig, "UICategoryNavigationConfig.msg.saving-success", null, ApplicationMessage.INFO);
        }
      }
    }
  }
  
  /**
   * The listener interface for receiving cancelAction events.
   * The class that is interested in processing a cancelAction
   * event implements this interface, and the object created
   * with that class is registered with a component using the
   * component's <code>addCancelActionListener<code> method. When
   * the cancelAction event occurs, that object's appropriate
   * method is invoked.
   * 
   * @see CancelActionEvent
   */
  public static class CancelActionListener extends EventListener<UICategoryNavigationConfig> {
    
    /* (non-Javadoc)
     * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
     */
    public void execute(Event<UICategoryNavigationConfig> event) throws Exception {
    	UICategoryNavigationConfig viewerManagementForm = event.getSource();
      Utils.closePopupWindow(viewerManagementForm, UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW);
      ((PortletRequestContext)event.getRequestContext()).setApplicationMode(PortletMode.VIEW);
    }
  }
  
  
  /**
   * The listener interface for receiving changeRepositoryAction events.
   * The class that is interested in processing a changeRepositoryAction
   * event implements this interface, and the object created
   * with that class is registered with a component using the
   * component's <code>addChangeRepositoryActionListener<code> method. When
   * the changeRepositoryAction event occurs, that object's appropriate
   * method is invoked.
   * 
   * @see ChangeRepositoryActionEvent
   */
  public static class ChangeRepositoryActionListener extends EventListener<UICategoryNavigationConfig> {
    
    /* (non-Javadoc)
     * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
     */
    public void execute(Event<UICategoryNavigationConfig> event) throws Exception {
    }
  }
  
  /**
   * The listener interface for receiving selectTargetPathAction events.
   * The class that is interested in processing a selectTargetPathAction
   * event implements this interface, and the object created
   * with that class is registered with a component using the
   * component's <code>addSelectTargetPathActionListener<code> method. When
   * the selectTargetPathAction event occurs, that object's appropriate
   * method is invoked.
   * 
   * @see SelectTargetPathActionEvent
   */
  public static class SelectTargetPathActionListener extends EventListener<UICategoryNavigationConfig> {
    
    /* (non-Javadoc)
     * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
     */
    public void execute(Event<UICategoryNavigationConfig> event) throws Exception {
      UICategoryNavigationConfig categoryNavigationConfig = event.getSource();
      UICategoryNavigationPortlet categoryNavigationPortlet = categoryNavigationConfig.getAncestorOfType(UICategoryNavigationPortlet.class);
      UIPopupContainer popupContainer = categoryNavigationPortlet.getChild(UIPopupContainer.class);
      UIPageSelector pageSelector = popupContainer.createUIComponent(UIPageSelector.class, null, null);
      pageSelector.setSourceComponent(categoryNavigationConfig, new String[] {UICategoryNavigationConstant.TARGET_PATH_FORM_STRING_INPUT});
      Utils.createPopupWindow(popupContainer, pageSelector, UICategoryNavigationConstant.TARGET_PATH_SELECTOR_POPUP_WINDOW, 700);
      categoryNavigationConfig.setPopupId(UICategoryNavigationConstant.TARGET_PATH_SELECTOR_POPUP_WINDOW);
    }
  }
}
