/**
 * Copyright (C) 2009 eXo Platform SAS.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.exoplatform.organization.webui.component;

import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.exoplatform.commons.serialization.api.annotations.Serialized;
import org.exoplatform.commons.utils.EmptySerializablePageList;
import org.exoplatform.commons.utils.PageList;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.organization.Group;
import org.exoplatform.services.organization.Membership;
import org.exoplatform.services.organization.MembershipHandler;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.UserHandler;
import org.exoplatform.services.organization.GroupHandler;
import org.exoplatform.web.application.AbstractApplicationMessage;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.ComponentConfigs;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIContainer;
import org.exoplatform.webui.core.UIGrid;
import org.exoplatform.webui.core.UIPageIterator;
import org.exoplatform.webui.core.UIPopupWindow;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.core.UIApplication;

/**
 * Created by The eXo Platform SARL Author : chungnv nguyenchung136@yahoo.com Jun 23, 2006 10:07:15 AM
 */
@ComponentConfigs({
        @ComponentConfig(events = {
                @EventConfig(listeners = UIUserInGroup.DeleteUserActionListener.class, confirm = "UIUserInGroup.confirm.deleteUser"),
                @EventConfig(listeners = UIUserInGroup.EditActionListener.class) }),
        @ComponentConfig(type = org.exoplatform.organization.webui.component.UIUserInGroup.UIGridUser.class, id = "UIGridUser", template = "system:/groovy/webui/core/UIGrid.gtmpl") })
@Serialized
public class UIUserInGroup extends UIContainer {

    private static String[] USER_BEAN_FIELD = { "userName", "firstName", "lastName", "membershipType", "email" };

    private static String[] USER_ACTION = { "Edit", "DeleteUser" };

    public UIUserInGroup() throws Exception {
        UIGrid uiGrid = addChild(UIGridUser.class, "UIGridUser", null);
        uiGrid.configure("id", USER_BEAN_FIELD, USER_ACTION);
        uiGrid.getUIPageIterator().setId("UIUserInGroupIterator");
        addChild(UIGroupMembershipForm.class, null, null);
        UIPopupWindow editMemberPopup = addChild(UIPopupWindow.class, null, "EditMembership");
        editMemberPopup.setWindowSize(400, 0);
    }

    @Override
    protected String loadConfirmMesssage(org.exoplatform.webui.config.Event event, WebuiRequestContext context, String beanId) {

        String confirm = event.getConfirm();
        if (confirm.length() < 1)
            return confirm;
        UIGridUser uiGrid = getChild(UIGridUser.class);
        try {
            confirm = context.getApplicationResourceBundle().getString(confirm);
            MembershipUser membershipUser = uiGrid.searchMembershipUser(beanId);
            if (membershipUser == null)
                return confirm;
            Group selectGroup = getSelectedGroup();
            if (selectGroup == null)
                return confirm;
            confirm = confirm.replaceAll("\\{0\\}", membershipUser.getUserName());
            confirm = confirm.replaceAll("\\{1\\}", selectGroup.getId().substring(1));
        } catch (Exception e) {

        }
        return confirm;
    }

    public Group getSelectedGroup() {
        UIOrganizationPortlet uiOrganizationPortlet = getAncestorOfType(UIOrganizationPortlet.class);
        UIGroupManagement uiGroupManagement = uiOrganizationPortlet.findFirstComponentOfType(UIGroupManagement.class);
        UIGroupExplorer uiGroupExplorer = uiGroupManagement.getChild(UIGroupExplorer.class);
        return uiGroupExplorer.getCurrentGroup();
    }

    public String getName() {
        return "UIUserInGroup";
    }

    public void refresh() throws Exception {
        Group selectedGroup = getSelectedGroup();
        OrganizationService service = getApplicationComponent(OrganizationService.class);
        if(selectedGroup != null) {
            String groupLabel = selectedGroup.getLabel();
            String parentGroup = selectedGroup.getParentId();
            GroupHandler gHandler = service.getGroupHandler();
            selectedGroup = gHandler.findGroupById(selectedGroup.getId());
            if(selectedGroup == null) {
                UIApplication uiApp = Util.getPortalRequestContext().getUIApplication();
                uiApp.addMessage(new ApplicationMessage("UIGroupForm.msg.group-not-exist", new Object[]{groupLabel}, AbstractApplicationMessage.WARNING));

                // Select to parent group
                String selectedId = parentGroup;
                while(selectedId != null && !selectedId.isEmpty()) {
                    if(gHandler.findGroupById(selectedId) != null) {
                        break;
                    } else {
                        selectedId = selectedId.substring(0, selectedId.lastIndexOf('/'));
                    }
                }

                UIOrganizationPortlet uiOrganizationPortlet = getAncestorOfType(UIOrganizationPortlet.class);
                UIGroupManagement uiGroupManagement = uiOrganizationPortlet.findFirstComponentOfType(UIGroupManagement.class);
                UIGroupExplorer uiGroupExplorer = uiGroupManagement.getChild(UIGroupExplorer.class);
                uiGroupExplorer.changeGroup(selectedId == null || selectedId.isEmpty() ? null : selectedId);
            }
        }
        setValues(selectedGroup);
    }

    public void setValues(Group group) throws Exception {
        PageList pageList = null;
        if (group == null) {
            pageList = EmptySerializablePageList.get();
        } else {
            pageList = new FindMembershipByGroupPageList(group.getId(), 5);
        }
        UIGridUser uiGrid = getChild(UIGridUser.class);

        UIPageIterator pageIterator = uiGrid.getUIPageIterator();
        /** We keep the currently selected page index **/
        int backupPageIndex = pageIterator.getCurrentPage();
        pageIterator.setPageList(pageList);

        if (group != null) {
            String groupId = group.getId();
            String currentUser = Util.getPortalRequestContext().getRemoteUser();

            // show action if user is administrator or manager of current group
            boolean showAction = GroupManagement.isAdministrator(currentUser)
                    || GroupManagement.isManagerOfGroup(currentUser, groupId);

            if (!showAction) {
                pageList.setPageSize(10);
                if (getChild(UIGroupMembershipForm.class) != null)
                    removeChild(UIGroupMembershipForm.class);
                uiGrid.configure("id", USER_BEAN_FIELD, null);
            } else {
                pageList.setPageSize(5);
                uiGrid.configure("id", USER_BEAN_FIELD, USER_ACTION);
                if (getChild(UIGroupMembershipForm.class) == null)
                    addChild(UIGroupMembershipForm.class, null, null);
            }
        } else {
            pageList.setPageSize(10);
            if (getChild(UIGroupMembershipForm.class) != null)
                removeChild(UIGroupMembershipForm.class);
        }

        /** Reset the selected page index **/
        if (backupPageIndex > pageIterator.getAvailablePage()) {
            backupPageIndex = pageIterator.getAvailablePage();
        }
        pageIterator.setCurrentPage(backupPageIndex);
    }

    public void processRender(WebuiRequestContext context) throws Exception {
        // TODO: Tung.Pham edded
        // -------------------------
        refresh();
        // -------------------------
        Writer w = context.getWriter();
        w.write("<div class=\"UIUserInGroup\">");
        renderChildren();
        w.write("</div>");
    }

    public static class DeleteUserActionListener extends EventListener<UIUserInGroup> {
        public void execute(Event<UIUserInGroup> event) throws Exception {
            UIUserInGroup uiUserInGroup = event.getSource();
            String id = event.getRequestContext().getRequestParameter(OBJECTID);
            OrganizationService service = uiUserInGroup.getApplicationComponent(OrganizationService.class);
            MembershipHandler handler = service.getMembershipHandler();
            handler.removeMembership(id, true);
            uiUserInGroup.refresh();
            event.getRequestContext().addUIComponentToUpdateByAjax(uiUserInGroup.getChild(UIGridUser.class));
        }
    }

    public static class EditActionListener extends EventListener<UIUserInGroup> {
        public void execute(Event<UIUserInGroup> event) throws Exception {
            UIUserInGroup uiUserInGroup = event.getSource();
            String id = event.getRequestContext().getRequestParameter(OBJECTID);
            OrganizationService service = uiUserInGroup.getApplicationComponent(OrganizationService.class);
            MembershipHandler handler = service.getMembershipHandler();
            UIPopupWindow uiPopup = uiUserInGroup.getChild(UIPopupWindow.class);
            UIGroupEditMembershipForm uiEditMemberShip = uiUserInGroup.createUIComponent(UIGroupEditMembershipForm.class, null,
                    null);
            uiEditMemberShip.setValue(handler.findMembership(id), uiUserInGroup.getSelectedGroup());
            uiPopup.setUIComponent(uiEditMemberShip);
            uiPopup.setShow(true);
        }
    }

    @Serialized
    public static class UIGridUser extends UIGrid {

        private List<MembershipUser> membershipUsers;

        public UIGridUser() throws Exception {
            super();
            membershipUsers = new ArrayList<MembershipUser>();
        }

        public List<?> getBeans() throws Exception {
            membershipUsers.clear();
            List<?> list = super.getBeans();
            Iterator<?> itr = list.iterator();
            while (itr.hasNext()) {
                Membership membership = (Membership) itr.next();
                MembershipUser mu = toMembershipUser(membership);
                if (mu != null)
                    membershipUsers.add(mu);
            }
            return membershipUsers;
        }

        private MembershipUser searchMembershipUser(String beanId) {
            for (MembershipUser ele : membershipUsers) {
                if (ele.id.equals(beanId))
                    return ele;
            }
            return null;
        }

        private MembershipUser toMembershipUser(Membership membership) throws Exception {
            OrganizationService service = getApplicationComponent(OrganizationService.class);
            String userName = membership.getUserName();
            UserHandler handler = service.getUserHandler();
            User user = handler.findUserByName(userName);
            if (user == null)
                return null;
            return new MembershipUser(user, membership.getMembershipType(), membership.getId());
        }

    }

    public static class MembershipUser implements Serializable {

        private String mtype;

        private String userName;

        private String firstName;

        private String lastName;

        private String email;

        private String id;

        public MembershipUser(User user, String mtype, String id) {
            this.mtype = mtype;
            this.userName = user.getUserName();
            this.firstName = user.getFirstName();
            this.lastName = user.getLastName();
            this.email = user.getEmail();
            this.id = id;
        }

        public String getMembershipType() {
            return mtype;
        }

        public void setMembershipType(String mtype) {
            this.mtype = mtype;
        }

        public String getUserName() {
            return userName;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public String getEmail() {
            return email;
        }

        public String getId() {
            return id;
        }
    }

}
