/* 
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  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.  
 */
package org.apache.wiki.ui;

import org.apache.log4j.Logger;
import org.apache.wiki.InternalWikiException;
import org.apache.wiki.WikiPage;
import org.apache.wiki.api.core.Command;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Page;
import org.apache.wiki.api.exceptions.ProviderException;
import org.apache.wiki.api.providers.WikiProvider;
import org.apache.wiki.auth.GroupPrincipal;
import org.apache.wiki.pages.PageManager;
import org.apache.wiki.parser.MarkupParser;
import org.apache.wiki.url.URLConstructor;
import org.apache.wiki.util.TextUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


/**
 * <p>Default implementation for {@link CommandResolver}</p>
 *
 * @since 2.4.22
 */
public final class DefaultCommandResolver implements CommandResolver {

    /** Private map with request contexts as keys, Commands as values */
    private static final Map< String, Command > CONTEXTS;

    /** Private map with JSPs as keys, Commands as values */
    private static final Map< String, Command > JSPS;

    /* Store the JSP-to-Command and context-to-Command mappings */
    static {
        CONTEXTS = new HashMap<>();
        JSPS = new HashMap<>();
        final Command[] commands = AbstractCommand.allCommands();
        for( final Command command : commands ) {
            JSPS.put( command.getJSP(), command );
            CONTEXTS.put( command.getRequestContext(), command );
        }
    }

    private static final Logger LOG = Logger.getLogger( DefaultCommandResolver.class );

    private final Engine m_engine;

    /** If true, we'll also consider english plurals (+s) a match. */
    private final boolean m_matchEnglishPlurals;

    /** Stores special page names as keys, and Commands as values. */
    private final Map<String, Command> m_specialPages;

    /**
     * Constructs a CommandResolver for a given Engine. This constructor will extract the special page references for this wiki and
     * store them in a cache used for resolution.
     *
     * @param engine the wiki engine
     * @param properties the properties used to initialize the wiki
     */
    public DefaultCommandResolver( final Engine engine, final Properties properties ) {
        m_engine = engine;
        m_specialPages = new HashMap<>();

        // Skim through the properties and look for anything with the "special page" prefix. Create maps that allow us look up
        // the correct Command based on special page name. If a matching command isn't found, create a RedirectCommand.
        for( final String key : properties.stringPropertyNames() ) {
            if ( key.startsWith( PROP_SPECIALPAGE ) ) {
                String specialPage = key.substring( PROP_SPECIALPAGE.length() );
                String jsp = properties.getProperty( key );
                if ( jsp != null ) {
                    specialPage = specialPage.trim();
                    jsp = jsp.trim();
                    Command command = JSPS.get( jsp );
                    if ( command == null ) {
                        final Command redirect = RedirectCommand.REDIRECT;
                        command = redirect.targetedCommand( jsp );
                    }
                    m_specialPages.put( specialPage, command );
                }
            }
        }

        // Do we match plurals?
        m_matchEnglishPlurals = TextUtil.getBooleanProperty( properties, Engine.PROP_MATCHPLURALS, true );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Command findCommand( final HttpServletRequest request, final String defaultContext ) {
        // Corner case if request is null
        if ( request == null ) {
            return CommandResolver.findCommand( defaultContext );
        }

        Command command = null;

        // Determine the name of the page (which may be null)
        String pageName = extractPageFromParameter( defaultContext, request );

        // Can we find a special-page command matching the extracted page?
        if ( pageName != null ) {
            command = m_specialPages.get( pageName );
        }

        // If we haven't found a matching command yet, extract the JSP path and compare to our list of special pages
        if ( command == null ) {
            command = extractCommandFromPath( request );

            // Otherwise: use the default context
            if ( command == null ) {
                command = CONTEXTS.get( defaultContext );
                if ( command == null ) {
                    throw new IllegalArgumentException( "Wiki context " + defaultContext + " is illegal." );
                }
            }
        }

        // For PageCommand.VIEW, default to front page if a page wasn't supplied
        if( PageCommand.VIEW.equals( command ) && pageName == null ) {
            pageName = m_engine.getFrontPage();
        }

        // These next blocks handle targeting requirements

        // If we were passed a page parameter, try to resolve it
        if ( command instanceof PageCommand && pageName != null ) {
            // If there's a matching WikiPage, "wrap" the command
            final Page page = resolvePage( request, pageName );
            return command.targetedCommand( page );
        }

        // If "create group" command, target this wiki
        final String wiki = m_engine.getApplicationName();
        if ( WikiCommand.CREATE_GROUP.equals( command ) ) {
            return WikiCommand.CREATE_GROUP.targetedCommand( wiki );
        }

        // If group command, see if we were passed a group name
        if( command instanceof GroupCommand ) {
            String groupName = request.getParameter( "group" );
            groupName = TextUtil.replaceEntities( groupName );
            if ( groupName != null && groupName.length() > 0 ) {
                final GroupPrincipal group = new GroupPrincipal( groupName );
                return command.targetedCommand( group );
            }
        }

        // No page provided; return an "ordinary" command
        return command;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getFinalPageName( final String page ) throws ProviderException {
        boolean isThere = simplePageExists( page );
        String  finalName = page;

        if ( !isThere && m_matchEnglishPlurals ) {
            if ( page.endsWith( "s" ) ) {
                finalName = page.substring( 0, page.length() - 1 );
            } else {
                finalName += "s";
            }

            isThere = simplePageExists( finalName );
        }

        if( !isThere ) {
            finalName = MarkupParser.wikifyLink( page );
            isThere = simplePageExists(finalName);

            if( !isThere && m_matchEnglishPlurals ) {
                if( finalName.endsWith( "s" ) ) {
                    finalName = finalName.substring( 0, finalName.length() - 1 );
                } else {
                    finalName += "s";
                }

                isThere = simplePageExists( finalName );
            }
        }

        return isThere ? finalName : null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSpecialPageReference( final String page ) {
        final Command command = m_specialPages.get( page );
        if ( command != null ) {
            return m_engine.getManager( URLConstructor.class ).makeURL( command.getRequestContext(), command.getURLPattern(), null );
        }

        return null;
    }

    /**
     * Extracts a Command based on the JSP path of an HTTP request. If the JSP requested matches a Command's <code>getJSP()</code>
     * value, that Command is returned.
     *
     * @param request the HTTP request
     * @return the resolved Command, or <code>null</code> if not found
     */
    protected Command extractCommandFromPath( final HttpServletRequest request ) {
        String jsp = request.getServletPath();

        // Take everything to right of initial / and left of # or ?
        final int hashMark = jsp.indexOf( '#' );
        if ( hashMark != -1 ) {
            jsp = jsp.substring( 0, hashMark );
        }
        final int questionMark = jsp.indexOf( '?' );
        if ( questionMark != -1 ) {
            jsp = jsp.substring( 0, questionMark );
        }
        if ( jsp.startsWith( "/" ) ) {
            jsp = jsp.substring( 1 );
        }

        // Find special page reference?
        for( final Map.Entry< String, Command > entry : m_specialPages.entrySet() ) {
            final Command specialCommand = entry.getValue();
            if( specialCommand.getJSP().equals( jsp ) ) {
                return specialCommand;
            }
        }

        // Still haven't found a matching command? Ok, see if we match against our standard list of JSPs
        if ( jsp.length() > 0 && JSPS.containsKey( jsp ) ) {
            return JSPS.get( jsp );
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String extractPageFromParameter( final String requestContext, final HttpServletRequest request ) {
        // Extract the page name from the URL directly
        try {
            String page = m_engine.getManager( URLConstructor.class ).parsePage( requestContext, request, m_engine.getContentEncoding() );
            if ( page != null ) {
                try {
                    // Look for singular/plural variants; if one not found, take the one the user supplied
                    final String finalPage = getFinalPageName( page );
                    if ( finalPage != null ) {
                        page = finalPage;
                    }
                } catch( final ProviderException e ) {
                    // FIXME: Should not ignore!
                }
                return page;
            }
        } catch( final IOException e ) {
            LOG.error( "Unable to create context", e );
            throw new InternalWikiException( "Big internal booboo, please check logs." , e );
        }

        // Didn't resolve; return null
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Page resolvePage( final HttpServletRequest request, String page ) {
        // See if the user included a version parameter
        int version = WikiProvider.LATEST_VERSION;
        final String rev = request.getParameter( "version" );
        if ( rev != null ) {
            try {
                version = Integer.parseInt( rev );
            } catch( final NumberFormatException e ) {
                // This happens a lot with bots or other guys who are trying to test if we are vulnerable to e.g. XSS attacks.  We catch
                // it here so that the admin does not get tons of mail.
            }
        }

        Page wikipage = m_engine.getManager( PageManager.class ).getPage( page, version );
        if ( wikipage == null ) {
            page = MarkupParser.cleanLink( page );
            wikipage = new WikiPage( m_engine, page );
        }
        return wikipage;
    }

    /**
     * Determines whether a "page" exists by examining the list of special pages and querying the page manager.
     *
     * @param page the page to seek
     * @return <code>true</code> if the page exists, <code>false</code> otherwise
     * @throws ProviderException if the underlyng page provider that locates pages
     * throws an exception
     */
    protected boolean simplePageExists( final String page ) throws ProviderException {
        if ( m_specialPages.containsKey( page ) ) {
            return true;
        }
        return m_engine.getManager( PageManager.class ).pageExists( page );
    }

}
