/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.ui.core.util.menu;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.UserManager;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
import org.apache.roller.weblogger.pojos.GlobalPermission;
import org.apache.roller.weblogger.pojos.User;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.pojos.WeblogPermission;
import org.apache.roller.weblogger.pojos.WeblogTheme;
import org.apache.roller.weblogger.util.Utilities;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

/**
 * A helper class for dealing with UI menus.
 * 
 * Note : Debug logging disabled here as it is too expensive time wise.
 * 
 */
public final class MenuHelper {

    private static Log log = LogFactory.getLog(MenuHelper.class);

    private static Map<String, ParsedMenu> menus = new HashMap<String, ParsedMenu>();

    // menu, menuName, tabName action/subaction check
    private static Map<String, HashMap<String, HashSet<String>>> itemMenu = new HashMap<String, HashMap<String, HashSet<String>>>();

    private MenuHelper() {
    }

    static {
        try {

            // parse menus and cache so we can efficiently reuse them
            String menu = "editor";
            ParsedMenu editorMenu = unmarshall( menu,
                MenuHelper.class.getResourceAsStream("/org/apache/roller/weblogger/ui/struts2/editor/editor-menu.xml"));
            menus.put(menu, editorMenu);

            menu = "admin";
            ParsedMenu adminMenu = unmarshall( menu,
                MenuHelper.class.getResourceAsStream("/org/apache/roller/weblogger/ui/struts2/admin/admin-menu.xml"));
            menus.put(menu, adminMenu);

        } catch (Exception ex) {
            log.error("Error parsing menu configs", ex);
        }
    }

    /**
     * Gets the menu.
     * 
     * @param menuId
     *            the menu id
     * @param currentAction
     *            the current action. Null to ignore.
     * @param user
     *            the user
     * @param weblog
     *            the weblog
     * 
     * @return the menu
     */
    public static Menu getMenu(String menuId, String currentAction, User user,
            Weblog weblog) {

        if (menuId == null) {
            return null;
        }

        Menu menu = null;

        // do we know the specified menu config?
        ParsedMenu menuConfig = menus.get(menuId);
        if (menuConfig != null) {
            try {
                menu = buildMenu(menuId, menuConfig, currentAction, user, weblog);
            } catch (WebloggerException ex) {
                log.error("ERROR: fethcing user roles", ex);
            }
        }

        return menu;
    }

    /**
     * Builds the menu.
     * 
     * @param menuId
     *            the menu id
     * @param menuConfig
     *            the menu config
     * @param currentAction
     *            the current action
     * @param user
     *            the user
     * @param weblog
     *            the weblog
     * 
     * @return the menu
     * 
     * @throws WebloggerException
     *             the weblogger exception
     */
    private static Menu buildMenu(String menuId, ParsedMenu menuConfig,
            String currentAction, User user, Weblog weblog)
            throws WebloggerException {

        // log.debug("creating menu for action - " + currentAction);

        Menu tabMenu = new Menu();
        UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();


        // Hack - for blogger convenience, the design tab of the edit
        // menu defaults to the templates tab item (instead of theme edit)
        // if the weblog is using a custom theme.
        boolean customThemeOverride = "editor".equals(menuId)
                && WeblogTheme.CUSTOM.equals(weblog.getEditorTheme());

        // iterate over tabs from parsed config
        for (ParsedTab configTab : menuConfig.getTabs()) {

            // log.debug("config tab = " + configTab.getName());

            // does this tab have an enabledProperty?
            boolean includeTab = true;
            if (configTab.getEnabledProperty() != null) {
                includeTab = getBooleanProperty(configTab.getEnabledProperty());
            } else if (configTab.getDisabledProperty() != null) {
                includeTab = !getBooleanProperty(configTab.getDisabledProperty());
            }

            // user roles check
            if (includeTab && configTab.getGlobalPermissionActions() != null
                    && !configTab.getGlobalPermissionActions().isEmpty()) {
                try {
                    GlobalPermission perm = new GlobalPermission( configTab.getGlobalPermissionActions());
                    if (!umgr.checkPermission(perm, user)) {
                        includeTab = false;
                    }
                } catch (WebloggerException ex) {
                    log.error("ERROR: fetching user roles", ex);
                    includeTab = false;
                }
            }

            // weblog permissions check
            if (includeTab && configTab.getWeblogPermissionActions() != null
                    && !configTab.getWeblogPermissionActions().isEmpty()) {
                WeblogPermission perm = new WeblogPermission(weblog, configTab.getWeblogPermissionActions());
                includeTab = umgr.checkPermission(perm, user);
            }

            if (includeTab) {

                // log.debug("tab allowed - " + configTab.getName());

                // all checks passed, tab should be included
                MenuTab tab = new MenuTab();
                tab.setKey(configTab.getName());

                // setup tab items
                boolean firstItem = true;
                boolean selectable = true;

                for (ParsedTabItem configTabItem : configTab.getTabItems()) {

                    boolean includeItem = true;

                    if (configTabItem.getEnabledProperty() != null) {
                        includeItem = getBooleanProperty(configTabItem.getEnabledProperty());
                    } else if (configTabItem.getDisabledProperty() != null) {
                        includeItem = !getBooleanProperty(configTabItem.getDisabledProperty());
                    }

                    // user roles check
                    if (includeItem
                            && configTabItem.getGlobalPermissionActions() != null
                            && !configTabItem.getGlobalPermissionActions() .isEmpty()) {
                        GlobalPermission perm = new GlobalPermission(
                                configTabItem.getGlobalPermissionActions());
                        if (!umgr.checkPermission(perm, user)) {
                            includeItem = false;
                        }
                    }

                    // weblog permissions check
                    if (includeItem
                            && configTabItem.getWeblogPermissionActions() != null
                            && !configTabItem.getWeblogPermissionActions().isEmpty()) {
                        WeblogPermission perm = new WeblogPermission(weblog, configTabItem.getWeblogPermissionActions());
                        includeItem = umgr.checkPermission(perm, user);
                    }

                    if (includeItem) {

                        // log.debug("tab item allowed - "
                        // + configTabItem.getName());

                        // all checks passed, item should be included
                        MenuTabItem tabItem = new MenuTabItem();
                        tabItem.setKey(configTabItem.getName());
                        tabItem.setAction(configTabItem.getAction());

                        // is this the selected item? Only one can be selected
                        // so skip the rest
                        if (currentAction != null && selectable
                                && isSelected(currentAction, configTabItem)) {
                            tabItem.setSelected(true);
                            tab.setSelected(true);
                            selectable = false;
                        }

                        // the url for the tab is the url of the first tab item
                        if (firstItem) {
                            if (customThemeOverride && "tabbedmenu.design".equals(tab.getKey())) {
                                tab.setAction("templates");
                            } else {
                                tab.setAction(tabItem.getAction());
                            }
                            firstItem = false;
                        }

                        // add the item
                        tab.addItem(tabItem);
                    }
                }

                // add the tab
                tabMenu.addTab(tab);
            }
        }

        return tabMenu;
    }

    /**
     * Check enabled property, prefers runtime properties.
     * 
     * @param propertyName
     *            the property name
     * 
     * @return the boolean property
     */
    private static boolean getBooleanProperty(String propertyName) {
        if (WebloggerRuntimeConfig.getProperty(propertyName) != null) {
            return WebloggerRuntimeConfig.getBooleanProperty(propertyName);
        }
        return WebloggerConfig.getBooleanProperty(propertyName);
    }

    /**
     * Checks if is selected.
     * 
     * @param currentAction
     *            the current action
     * @param tabItem
     *            the tab item
     * 
     * @return true, if is selected
     */
    private static boolean isSelected(String currentAction,
            ParsedTabItem tabItem) {

        if (currentAction.equals(tabItem.getAction())) {
            return true;
        }

        // an item is also considered selected if it's a subforward of the
        // current action
        Set<String> subActions = tabItem.getSubActions();

        return subActions != null && subActions.contains(currentAction);
    }

    /**
     * Unmarshall the given input stream into our defined set of Java objects.
     * 
     * @param menuId
     *            the menu id
     * @param instream
     *            the instream
     * 
     * @return the parsed menu
     * 
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws JDOMException
     *             the jDOM exception
     */
    private static ParsedMenu unmarshall(String menuId, InputStream instream)
            throws IOException, JDOMException {

        if (instream == null) {
            throw new IOException("InputStream is null!");
        }

        ParsedMenu config = new ParsedMenu();

        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(instream);

        Element root = doc.getRootElement();
        List<Element> parsedMenus = root.getChildren("menu");
        for (Element e : parsedMenus) {
            config.addTab(elementToParsedTab(menuId, e));
        }

        return config;
    }

    /**
     * Element to parsed tab.
     * 
     * @param menuId
     *            the menu id
     * @param element
     *            the element
     * 
     * @return the parsed tab
     */
    private static ParsedTab elementToParsedTab(String menuId, Element element) {

        ParsedTab tab = new ParsedTab();

        tab.setName(element.getAttributeValue("name"));
        if (element.getAttributeValue("weblogPerms") != null) {
            tab.setWeblogPermissionActions(Utilities.stringToStringList(
                    element.getAttributeValue("weblogPerms"), ","));
        }
        if (element.getAttributeValue("globalPerms") != null) {
            tab.setGlobalPermissionActions(Utilities.stringToStringList(
                    element.getAttributeValue("globalPerms"), ","));
        }
        tab.setEnabledProperty(element.getAttributeValue("enabledProperty"));
        tab.setDisabledProperty(element.getAttributeValue("disabledProperty"));

        List<Element> menuItems = element.getChildren("menu-item");

        // Build our tab action relation
        HashMap<String, HashSet<String>> menu = itemMenu.get(menuId);
        if (menu == null) {
            menu = new HashMap<String, HashSet<String>>();
        }

        for (Element e : menuItems) {

            ParsedTabItem tabItem = elementToParsedTabItem(e);

            HashSet<String> item = menu.get(tab.getName());
            if (item != null) {
                if (!item.contains(tabItem.getAction())) {
                    item.add(tabItem.getAction());
                }
            } else {
                item = new HashSet<String>();
                item.add(tabItem.getAction());
            }

            // Add subaction items
            Set<String> subActions = tabItem.getSubActions();
            if (subActions != null) {
                for (String subAction : subActions) {
                    if (!item.contains(subAction)) {
                        item.add(subAction);
                    }
                }
            }

            // save our tab action relation
            menu.put(tab.getName(), item);

            tab.addItem(tabItem);

        }

        // Save relation
        itemMenu.put(menuId, menu);

        return tab;
    }

    /**
     * Element to parsed tab item.
     * 
     * @param element
     *            the element
     * 
     * @return the parsed tab item
     */
    private static ParsedTabItem elementToParsedTabItem(Element element) {

        ParsedTabItem tabItem = new ParsedTabItem();

        tabItem.setName(element.getAttributeValue("name"));
        tabItem.setAction(element.getAttributeValue("action"));

        String subActions = element.getAttributeValue("subactions");
        if (subActions != null) {
            Set<String> set = new HashSet<String>();
            for (String string : Utilities.stringToStringList(subActions, ",")) {
                set.add(string);
            }
            tabItem.setSubActions(set);
        }

        if (element.getAttributeValue("weblogPerms") != null) {
            tabItem.setWeblogPermissionActions(Utilities.stringToStringList(
                    element.getAttributeValue("weblogPerms"), ","));
        }
        if (element.getAttributeValue("globalPerms") != null) {
            tabItem.setGlobalPermissionActions(Utilities.stringToStringList(
                    element.getAttributeValue("globalPerms"), ","));
        }
        tabItem.setEnabledProperty(element.getAttributeValue("enabledProperty"));
        tabItem.setDisabledProperty(element.getAttributeValue("disabledProperty"));

        return tabItem;
    }

}
