/*
 * 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.newsletter.manager;

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

import org.exoplatform.container.PortalContainer;
import org.exoplatform.ecm.webui.selector.UIGroupMemberSelector;
import org.exoplatform.ecm.webui.selector.UISelectable;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.wcm.newsletter.NewsletterCategoryConfig;
import org.exoplatform.services.wcm.newsletter.NewsletterConstant;
import org.exoplatform.services.wcm.newsletter.NewsletterManagerService;
import org.exoplatform.services.wcm.newsletter.handler.NewsletterCategoryHandler;
import org.exoplatform.wcm.webui.Utils;
import org.exoplatform.wcm.webui.newsletter.NoneHTMLValidator;
import org.exoplatform.wcm.webui.newsletter.UINewsletterConstant;
import org.exoplatform.wcm.webui.selector.UIUserMemberSelector;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIApplication;
import org.exoplatform.webui.core.UIPopupComponent;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.event.Event.Phase;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormStringInput;
import org.exoplatform.webui.form.UIFormTextAreaInput;
import org.exoplatform.webui.form.ext.UIFormInputSetWithAction;
import org.exoplatform.webui.form.validator.MandatoryValidator;
import org.exoplatform.webui.form.validator.NameValidator;
import org.exoplatform.webui.form.validator.SpecialCharacterValidator;

/**
 * The Class UICategoryForm.
 */
@ComponentConfig(
		lifecycle = UIFormLifecycle.class ,
		template = "system:/groovy/webui/form/UIForm.gtmpl",
		events = {
			@EventConfig(listeners = UICategoryForm.SaveActionListener.class),
			@EventConfig(listeners = UICategoryForm.CancelActionListener.class, phase = Phase.DECODE),
			@EventConfig(listeners = UICategoryForm.DeleteModeratorActionListener.class, phase = Phase.DECODE),
			@EventConfig(listeners = UICategoryForm.SelectUserActionListener.class, phase = Phase.DECODE),
			@EventConfig(listeners = UICategoryForm.SelectMemberActionListener.class, phase = Phase.DECODE)
		}
)
public class UICategoryForm extends UIForm implements UIPopupComponent, UISelectable {
  
  /** The category config. */
  private NewsletterCategoryConfig categoryConfig;
  
  /** The popup id. */
  private String popupId;
  
  /** The Constant INPUT_CATEGORY_NAME. */
  public static final String INPUT_CATEGORY_NAME           = "CategoryName"; 
	
	/** The Constant INPUT_CATEGORY_TITLE. */
	public static final String INPUT_CATEGORY_TITLE          = "CategoryTitle"; 
	
	/** The Constant INPUT_CATEGORY_DESCRIPTION. */
	public static final String INPUT_CATEGORY_DESCRIPTION    = "CategoryDescription";
	
	/** The Constant FORM_CATEGORY_MODERATOR. */
	public static final String FORM_CATEGORY_MODERATOR       = "FormCategoryModerator";
	
	/** The Constant INPUT_CATEGORY_MODERATOR. */
	public static final String INPUT_CATEGORY_MODERATOR      = "CategoryModerator"; 
	
	private boolean isRemove;

	public boolean isRemove() {
    return isRemove;
  }

  public void setRemove(boolean isRemove) {
    this.isRemove = isRemove;
  }

  /**
	 * Instantiates a new uI category form.
	 * 
	 * @throws Exception the exception
	 */
	public UICategoryForm() throws Exception{
		UIFormStringInput inputCateName = new UIFormStringInput(INPUT_CATEGORY_NAME, null, null);
		UIFormStringInput inputCateTitle = new UIFormStringInput(INPUT_CATEGORY_TITLE, null, null);
	  this.getChildren().clear();
		UIFormTextAreaInput inputCateDescription = new UIFormTextAreaInput(INPUT_CATEGORY_DESCRIPTION, null, null);
		UIFormStringInput inputModerator = new UIFormStringInput(INPUT_CATEGORY_MODERATOR, INPUT_CATEGORY_MODERATOR, null);
		inputModerator.setEditable(false);
		UIFormInputSetWithAction formCategoryModerator = new UIFormInputSetWithAction(FORM_CATEGORY_MODERATOR);
		formCategoryModerator.addChild(inputModerator);
		formCategoryModerator.setActionInfo(INPUT_CATEGORY_MODERATOR, new String[] {"SelectUser", "SelectMember", "DeleteModerator"});
		formCategoryModerator.showActionInfo(true);
		
		inputCateName.addValidator(MandatoryValidator.class).addValidator(NameValidator.class)
									.addValidator(SpecialCharacterValidator.class);;
		inputCateTitle.addValidator(MandatoryValidator.class).addValidator(NoneHTMLValidator.class);
		inputModerator.addValidator(MandatoryValidator.class);
		inputCateDescription.addValidator(NoneHTMLValidator.class);
		
		addChild(inputCateName);
		addChild(inputCateTitle);
		addChild(inputCateDescription);
		addChild(formCategoryModerator);
		setActions(new String[]{"Save", "Cancel"});
	}

  /* (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 {
    UIFormInputSetWithAction formCategoryModerator = getChildById(FORM_CATEGORY_MODERATOR);
    UIFormStringInput stringInput = formCategoryModerator.getChildById(selectField);
    List<String> values = new ArrayList<String>();
    String oldValue = stringInput.getValue();
    if(oldValue != null && oldValue.length() > 0)
      values.addAll(Arrays.asList(oldValue.split(",")));
    String result = (String) value;
    if(!values.contains(result)) values.add(result);
    result = "";
    for(String str : values){
      if(result.trim().length() > 0) result += ",";
      result += str;
    }
    stringInput.setValue(result);
    Utils.closePopupWindow(this, popupId);
  }

  /**
   * 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;
  }
  
  /* (non-Javadoc)
   * @see org.exoplatform.webui.core.UIPopupComponent#activate()
   */
  public void activate() throws Exception {}

  /* (non-Javadoc)
   * @see org.exoplatform.webui.core.UIPopupComponent#deActivate()
   */
  public void deActivate() throws Exception {}
  
	/**
	 * Sets the category info.
	 * 
	 * @param categoryConfig the new category info
	 */
	public void setCategoryInfo(NewsletterCategoryConfig categoryConfig){
	  if(categoryConfig == null) return;
	  this.categoryConfig = categoryConfig;
	  UIFormStringInput inputCateName = this.getChildById(INPUT_CATEGORY_NAME);
	  inputCateName.setValue(categoryConfig.getName());
	  inputCateName.setEditable(false);
    UIFormStringInput inputCateTitle = this.getChildById(INPUT_CATEGORY_TITLE);
    inputCateTitle.setValue(categoryConfig.getTitle());
    UIFormTextAreaInput inputCateDescription = this.getChildById(INPUT_CATEGORY_DESCRIPTION);
    inputCateDescription.setValue(categoryConfig.getDescription());
    UIFormInputSetWithAction inputSetWithAction = getChildById(FORM_CATEGORY_MODERATOR);
    UIFormStringInput inputModerator = inputSetWithAction.getChildById(INPUT_CATEGORY_MODERATOR);
    inputModerator.setValue(categoryConfig.getModerator());
    
	}
	
	/**
	 * 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
	 */
	static  public class SaveActionListener extends EventListener<UICategoryForm> {
		
		/* (non-Javadoc)
		 * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
		 */
		public void execute(Event<UICategoryForm> event) throws Exception {
			UICategoryForm uiCategoryForm = event.getSource();
			NewsletterManagerService newsletterManagerService = 
				(NewsletterManagerService)PortalContainer.getInstance().getComponentInstanceOfType(NewsletterManagerService.class) ;
			NewsletterCategoryConfig categoryConfig = null;
			if(uiCategoryForm.categoryConfig == null) {
			  categoryConfig = new NewsletterCategoryConfig();
			  categoryConfig.setName(((UIFormStringInput)uiCategoryForm.getChildById(INPUT_CATEGORY_NAME)).getValue());
			}else{
			  categoryConfig = uiCategoryForm.categoryConfig;
			}
			categoryConfig.setTitle(((UIFormStringInput)uiCategoryForm.getChildById(INPUT_CATEGORY_TITLE)).getValue());
			categoryConfig.setDescription(((UIFormTextAreaInput)uiCategoryForm.getChildById(INPUT_CATEGORY_DESCRIPTION)).getValue());
			
			UIFormInputSetWithAction inputSetWithAction = uiCategoryForm.getChildById(FORM_CATEGORY_MODERATOR);
      UIFormStringInput inputModerator = inputSetWithAction.getChildById(INPUT_CATEGORY_MODERATOR);
      
      String inputModeratorValue = inputModerator.getValue();
      if (("".equals(inputModeratorValue)) || (inputModeratorValue == null)) {
        UIApplication uiApp = uiCategoryForm.getAncestorOfType(UIApplication.class);
        uiApp.addMessage(new ApplicationMessage("UICategoryForm.msg.inputModeratorEmpty", null, ApplicationMessage.WARNING));
        event.getRequestContext().addUIComponentToUpdateByAjax(uiApp.getUIPopupMessages());
        return;
      }
      categoryConfig.setModerator(inputModeratorValue); 
      
      // Update access permission into newsletter manager page for moderators
      NewsletterConstant.updateAccessPermission(inputModeratorValue.split(","));
			UIApplication uiApp = uiCategoryForm.getAncestorOfType(UIApplication.class);
			NewsletterCategoryHandler categoryHandler = newsletterManagerService.getCategoryHandler();
			categoryHandler.setRemove(uiCategoryForm.isRemove());
			String portalName = NewsLetterUtil.getPortalName(); 
			try{
				SessionProvider sessionProvider = Utils.getSessionProvider();
			  if(uiCategoryForm.categoryConfig == null){ // if add new category then check cateogry's name is already exist or not
  			  if(categoryHandler.getCategoryByName(sessionProvider, portalName, categoryConfig.getName()) != null){
  			    uiApp.addMessage(new ApplicationMessage("UICategoryForm.msg.categoryNameIsAlreadyExist", null, ApplicationMessage.WARNING));
  			    event.getRequestContext().addUIComponentToUpdateByAjax(uiApp.getUIPopupMessages());
  			    return;
  			  }else{
  			    categoryHandler.add(sessionProvider, portalName, categoryConfig);
  			  }
			  }else{ // Edit a category is already exist
			    categoryHandler.edit(sessionProvider, portalName, categoryConfig);
			  }
			}catch(Exception ex){
			  Utils.createPopupMessage(uiCategoryForm, "UICategoryForm.msg.error-add-category", null, ApplicationMessage.ERROR);
			}
			Utils.closePopupWindow(uiCategoryForm, UINewsletterConstant.CATEGORY_FORM_POPUP_WINDOW);
		}
	}
	
	/**
	 * 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
	 */
	static  public class CancelActionListener extends EventListener<UICategoryForm> {
		
		/* (non-Javadoc)
		 * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
		 */
		public void execute(Event<UICategoryForm> event) throws Exception {
			UICategoryForm uiCategoryForm = event.getSource();
			uiCategoryForm.setRemove(false);
			Utils.closePopupWindow(uiCategoryForm, UINewsletterConstant.CATEGORY_FORM_POPUP_WINDOW);
		}
	}

	/**
	 * The listener interface for receiving selectUserAction events.
	 * The class that is interested in processing a selectUserAction
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's <code>addSelectUserActionListener<code> method. When
	 * the selectUserAction event occurs, that object's appropriate
	 * method is invoked.
	 * 
	 * @see SelectUserActionEvent
	 */
	public static class SelectUserActionListener extends EventListener<UICategoryForm> {
	  
  	/* (non-Javadoc)
  	 * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
  	 */
  	public void execute(Event<UICategoryForm> event) throws Exception {
	    UICategoryForm categoryForm = event.getSource();
	    categoryForm.setRemove(false);
      UIUserMemberSelector userMemberSelector = categoryForm.createUIComponent(UIUserMemberSelector.class, null, null);
      userMemberSelector.setMulti(false);
      userMemberSelector.setShowSearch(true);
      userMemberSelector.setSourceComponent(categoryForm, new String[] {INPUT_CATEGORY_MODERATOR});
      userMemberSelector.init();
      Utils.createPopupWindow(categoryForm, userMemberSelector, UINewsletterConstant.USER_SELECTOR_POPUP_WINDOW, 750);
      categoryForm.setPopupId(UINewsletterConstant.USER_SELECTOR_POPUP_WINDOW);
	  }
	}

	/**
	 * The listener interface for receiving selectMemberAction events.
	 * The class that is interested in processing a selectMemberAction
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's <code>addSelectMemberActionListener<code> method. When
	 * the selectMemberAction event occurs, that object's appropriate
	 * method is invoked.
	 * 
	 * @see SelectMemberActionEvent
	 */
	public static class SelectMemberActionListener extends EventListener<UICategoryForm> {
	  
  	/* (non-Javadoc)
  	 * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
  	 */
  	public void execute(Event<UICategoryForm> event) throws Exception {
	    UICategoryForm categoryForm = event.getSource();
	    categoryForm.setRemove(false);
      UIGroupMemberSelector groupMemberSelector = categoryForm.createUIComponent(UIGroupMemberSelector.class, null, null);
      groupMemberSelector.setShowAnyPermission(false);
      groupMemberSelector.setSourceComponent(categoryForm, new String[] {INPUT_CATEGORY_MODERATOR});
      Utils.createPopupWindow(categoryForm, groupMemberSelector, UINewsletterConstant.GROUP_SELECTOR_POPUP_WINDOW, 540);
	    categoryForm.setPopupId(UINewsletterConstant.GROUP_SELECTOR_POPUP_WINDOW);
	  }
	}
	
	public static class DeleteModeratorActionListener extends EventListener<UICategoryForm> {
	  
	  /* (non-Javadoc)
	   * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
	   */
	  public void execute(Event<UICategoryForm> event) throws Exception {
	    UICategoryForm categoryForm = event.getSource();
	    UIFormInputSetWithAction formCategoryModerator = categoryForm.getChildById(FORM_CATEGORY_MODERATOR);
	    UIFormStringInput stringInput = formCategoryModerator.getChildById(INPUT_CATEGORY_MODERATOR);
	    if(stringInput.getValue() == null || stringInput.getValue().trim().length() < 1) {
	      UIApplication uiApp = categoryForm.getAncestorOfType(UIApplication.class);
	      uiApp.addMessage(new ApplicationMessage("UICategoryForm.msg.doNotHaveModerators", null, ApplicationMessage.WARNING));
        event.getRequestContext().addUIComponentToUpdateByAjax(uiApp.getUIPopupMessages());
        return;
	    };
	    UIRemoveModerators removeModerators = categoryForm.createUIComponent(UIRemoveModerators.class, null, null);
	    removeModerators.init(((UIFormStringInput)((UIFormInputSetWithAction)categoryForm.
	                          getChildById(FORM_CATEGORY_MODERATOR)).getChildById(INPUT_CATEGORY_MODERATOR)).getValue());
	    categoryForm.setRemove(true);
	    Utils.createPopupWindow(categoryForm, removeModerators, UINewsletterConstant.REMOVE_MODERATORS_FORM_POPUP_WINDOW, 480);
	    categoryForm.setPopupId(UINewsletterConstant.REMOVE_MODERATORS_FORM_POPUP_WINDOW);
	  }
	}
}