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

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.wiki.ajax.AjaxUtil;
import org.apache.wiki.ajax.WikiAjaxDispatcherServlet;
import org.apache.wiki.ajax.WikiAjaxServlet;
import org.apache.wiki.api.core.Context;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Session;
import org.apache.wiki.api.exceptions.NoRequiredPropertyException;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.api.filters.PageFilter;
import org.apache.wiki.auth.permissions.AllPermission;
import org.apache.wiki.auth.permissions.WikiPermission;
import org.apache.wiki.auth.user.DummyUserDatabase;
import org.apache.wiki.auth.user.DuplicateUserException;
import org.apache.wiki.auth.user.UserDatabase;
import org.apache.wiki.auth.user.UserProfile;
import org.apache.wiki.event.WikiEventListener;
import org.apache.wiki.event.WikiEventManager;
import org.apache.wiki.event.WikiSecurityEvent;
import org.apache.wiki.filters.FilterManager;
import org.apache.wiki.filters.SpamFilter;
import org.apache.wiki.i18n.InternationalizationManager;
import org.apache.wiki.pages.PageManager;
import org.apache.wiki.preferences.Preferences;
import org.apache.wiki.tasks.TasksManager;
import org.apache.wiki.ui.InputValidator;
import org.apache.wiki.util.ClassUtil;
import org.apache.wiki.util.TextUtil;
import org.apache.wiki.workflow.Decision;
import org.apache.wiki.workflow.DecisionRequiredException;
import org.apache.wiki.workflow.Fact;
import org.apache.wiki.workflow.Step;
import org.apache.wiki.workflow.Workflow;
import org.apache.wiki.workflow.WorkflowBuilder;
import org.apache.wiki.workflow.WorkflowManager;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Permission;
import java.security.Principal;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.WeakHashMap;


/**
 * Default implementation for {@link UserManager}.
 *
 * @since 2.3
 */
public class DefaultUserManager implements UserManager {

    private static final String USERDATABASE_PACKAGE = "org.apache.wiki.auth.user";
    private static final String SESSION_MESSAGES = "profile";
    private static final String PARAM_EMAIL = "email";
    private static final String PARAM_FULLNAME = "fullname";
    private static final String PARAM_PASSWORD = "password";
    private static final String PARAM_LOGINNAME = "loginname";
    private static final String UNKNOWN_CLASS = "<unknown>";

    private Engine m_engine;

    private static final Logger log = Logger.getLogger( DefaultUserManager.class);

    /** Associates wiki sessions with profiles */
    private final Map< Session, UserProfile > m_profiles = new WeakHashMap<>();

    /** The user database loads, manages and persists user identities */
    private UserDatabase m_database;

    /** {@inheritDoc} */
    @Override
    public void initialize( final Engine engine, final Properties props ) {
        m_engine = engine;

        // Attach the PageManager as a listener
        // TODO: it would be better if we did this in PageManager directly
        addWikiEventListener( engine.getManager( PageManager.class ) );

        //TODO: Replace with custom annotations. See JSPWIKI-566
        WikiAjaxDispatcherServlet.registerServlet( JSON_USERS, new JSONUserModule(this), new AllPermission(null));
    }

    /** {@inheritDoc} */
    @Override
    public UserDatabase getUserDatabase() {
        if( m_database != null ) {
            return m_database;
        }

        String dbClassName = UNKNOWN_CLASS;

        try {
            dbClassName = TextUtil.getRequiredProperty( m_engine.getWikiProperties(), PROP_DATABASE );

            log.info( "Attempting to load user database class " + dbClassName );
            final Class<?> dbClass = ClassUtil.findClass( USERDATABASE_PACKAGE, dbClassName );
            m_database = (UserDatabase) dbClass.newInstance();
            m_database.initialize( m_engine, m_engine.getWikiProperties() );
            log.info("UserDatabase initialized.");
        } catch( final NoSuchElementException | NoRequiredPropertyException e ) {
            log.error( "You have not set the '"+PROP_DATABASE+"'. You need to do this if you want to enable user management by JSPWiki.", e );
        } catch( final ClassNotFoundException e ) {
            log.error( "UserDatabase class " + dbClassName + " cannot be found", e );
        } catch( final InstantiationException e ) {
            log.error( "UserDatabase class " + dbClassName + " cannot be created", e );
        } catch( final IllegalAccessException e ) {
            log.error( "You are not allowed to access this user database class", e );
        } catch( final WikiSecurityException e ) {
            log.error( "Exception initializing user database: " + e.getMessage(), e );
        } finally {
            if( m_database == null ) {
                log.info("I could not create a database object you specified (or didn't specify), so I am falling back to a default.");
                m_database = new DummyUserDatabase();
            }
        }

        return m_database;
    }

    /** {@inheritDoc} */
    @Override
    public UserProfile getUserProfile( final Session session ) {
        // Look up cached user profile
        UserProfile profile = m_profiles.get( session );
        boolean newProfile = profile == null;
        Principal user = null;

        // If user is authenticated, figure out if this is an existing profile
        if ( session.isAuthenticated() ) {
            user = session.getUserPrincipal();
            try {
                profile = getUserDatabase().find( user.getName() );
                newProfile = false;
            } catch( final NoSuchPrincipalException e ) { }
        }

        if ( newProfile ) {
            profile = getUserDatabase().newProfile();
            if ( user != null ) {
                profile.setLoginName( user.getName() );
            }
            if ( !profile.isNew() ) {
                throw new IllegalStateException( "New profile should be marked 'new'. Check your UserProfile implementation." );
            }
        }

        // Stash the profile for next time
        m_profiles.put( session, profile );
        return profile;
    }

    /** {@inheritDoc} */
    @Override
    public void setUserProfile( final Session session, final UserProfile profile ) throws DuplicateUserException, WikiException {
        // Verify user is allowed to save profile!
        final Permission p = new WikiPermission( m_engine.getApplicationName(), WikiPermission.EDIT_PROFILE_ACTION );
        if ( !m_engine.getManager( AuthorizationManager.class ).checkPermission( session, p ) ) {
            throw new WikiSecurityException( "You are not allowed to save wiki profiles." );
        }

        // Check if profile is new, and see if container allows creation
        final boolean newProfile = profile.isNew();

        // Check if another user profile already has the fullname or loginname
        final UserProfile oldProfile = getUserProfile( session );
        final boolean nameChanged = ( oldProfile != null && oldProfile.getFullname() != null ) &&
                                    !( oldProfile.getFullname().equals( profile.getFullname() ) &&
                                    oldProfile.getLoginName().equals( profile.getLoginName() ) );
        UserProfile otherProfile;
        try {
            otherProfile = getUserDatabase().findByLoginName( profile.getLoginName() );
            if( otherProfile != null && !otherProfile.equals( oldProfile ) ) {
                throw new DuplicateUserException( "security.error.login.taken", profile.getLoginName() );
            }
        } catch( final NoSuchPrincipalException e ) {
        }
        try {
            otherProfile = getUserDatabase().findByFullName( profile.getFullname() );
            if( otherProfile != null && !otherProfile.equals( oldProfile ) ) {
                throw new DuplicateUserException( "security.error.fullname.taken", profile.getFullname() );
            }
        } catch( final NoSuchPrincipalException e ) {
        }

        // For new accounts, create approval workflow for user profile save.
        if( newProfile && oldProfile != null && oldProfile.isNew() ) {
            startUserProfileCreationWorkflow( session, profile );

            // If the profile doesn't need approval, then just log the user in

            try {
                final AuthenticationManager mgr = m_engine.getManager( AuthenticationManager.class );
                if( !mgr.isContainerAuthenticated() ) {
                    mgr.login( session, null, profile.getLoginName(), profile.getPassword() );
                }
            } catch( final WikiException e ) {
                throw new WikiSecurityException( e.getMessage(), e );
            }

            // Alert all listeners that the profile changed...
            // ...this will cause credentials to be reloaded in the wiki session
            fireEvent( WikiSecurityEvent.PROFILE_SAVE, session, profile );
        } else { // For existing accounts, just save the profile
            // If login name changed, rename it first
            if( nameChanged && !oldProfile.getLoginName().equals( profile.getLoginName() ) ) {
                getUserDatabase().rename( oldProfile.getLoginName(), profile.getLoginName() );
            }

            // Now, save the profile (userdatabase will take care of timestamps for us)
            getUserDatabase().save( profile );

            if( nameChanged ) {
                // Fire an event if the login name or full name changed
                final UserProfile[] profiles = new UserProfile[] { oldProfile, profile };
                fireEvent( WikiSecurityEvent.PROFILE_NAME_CHANGED, session, profiles );
            } else {
                // Fire an event that says we have new a new profile (new principals)
                fireEvent( WikiSecurityEvent.PROFILE_SAVE, session, profile );
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void startUserProfileCreationWorkflow( final Session session, final UserProfile profile ) throws WikiException {
        final WorkflowBuilder builder = WorkflowBuilder.getBuilder( m_engine );
        final Principal submitter = session.getUserPrincipal();
        final Step completionTask = m_engine.getManager( TasksManager.class ).buildSaveUserProfileTask( m_engine, session.getLocale() );

        // Add user profile attribute as Facts for the approver (if required)
        final boolean hasEmail = profile.getEmail() != null;
        final Fact[] facts = new Fact[ hasEmail ? 4 : 3 ];
        facts[ 0 ] = new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_FULL_NAME, profile.getFullname() );
        facts[ 1 ] = new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_LOGIN_NAME, profile.getLoginName() );
        facts[ 2 ] = new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_SUBMITTER, submitter.getName() );
        if ( hasEmail ) {
            facts[ 3 ] = new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_EMAIL, profile.getEmail() );
        }
        final Workflow workflow = builder.buildApprovalWorkflow( submitter,
                                                                 WorkflowManager.WF_UP_CREATE_SAVE_APPROVER,
                                                                 null,
                                                                 WorkflowManager.WF_UP_CREATE_SAVE_DECISION_MESSAGE_KEY,
                                                                 facts,
                                                                 completionTask,
                                                                 null );

        workflow.setAttribute( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE, profile );
        m_engine.getManager( WorkflowManager.class ).start( workflow );

        final boolean approvalRequired = workflow.getCurrentStep() instanceof Decision;

        // If the profile requires approval, redirect user to message page
        if ( approvalRequired ) {
            throw new DecisionRequiredException( "This profile must be approved before it becomes active" );
        }
    }

    /** {@inheritDoc} */
    @Override
    public UserProfile parseProfile( final Context context ) {
        // Retrieve the user's profile (may have been previously cached)
        final UserProfile profile = getUserProfile( context.getWikiSession() );
        final HttpServletRequest request = context.getHttpRequest();

        // Extract values from request stream (cleanse whitespace as needed)
        String loginName = request.getParameter( PARAM_LOGINNAME );
        String password = request.getParameter( PARAM_PASSWORD );
        String fullname = request.getParameter( PARAM_FULLNAME );
        String email = request.getParameter( PARAM_EMAIL );
        loginName = InputValidator.isBlank( loginName ) ? null : loginName;
        password = InputValidator.isBlank( password ) ? null : password;
        fullname = InputValidator.isBlank( fullname ) ? null : fullname;
        email = InputValidator.isBlank( email ) ? null : email;

        // A special case if we have container authentication: if authenticated, login name is always taken from container
        if ( m_engine.getManager( AuthenticationManager.class ).isContainerAuthenticated() && context.getWikiSession().isAuthenticated() ) {
            loginName = context.getWikiSession().getLoginPrincipal().getName();
        }

        // Set the profile fields!
        profile.setLoginName( loginName );
        profile.setEmail( email );
        profile.setFullname( fullname );
        profile.setPassword( password );
        return profile;
    }

    /** {@inheritDoc} */
    @Override
    public void validateProfile( final Context context, final UserProfile profile ) {
        final boolean isNew = profile.isNew();
        final Session session = context.getWikiSession();
        final InputValidator validator = new InputValidator( SESSION_MESSAGES, context );
        final ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE );

        //  Query the SpamFilter first
        final FilterManager fm = m_engine.getManager( FilterManager.class );
        final List< PageFilter > ls = fm.getFilterList();
        for( final PageFilter pf : ls ) {
            if( pf instanceof SpamFilter ) {
                if( !( ( SpamFilter )pf ).isValidUserProfile( context, profile ) ) {
                    session.addMessage( SESSION_MESSAGES, "Invalid userprofile" );
                    return;
                }
                break;
            }
        }

        // If container-managed auth and user not logged in, throw an error
        if ( m_engine.getManager( AuthenticationManager.class ).isContainerAuthenticated()
             && !context.getWikiSession().isAuthenticated() ) {
            session.addMessage( SESSION_MESSAGES, rb.getString("security.error.createprofilebeforelogin") );
        }

        validator.validateNotNull( profile.getLoginName(), rb.getString("security.user.loginname") );
        validator.validateNotNull( profile.getFullname(), rb.getString("security.user.fullname") );
        validator.validate( profile.getEmail(), rb.getString("security.user.email"), InputValidator.EMAIL );

        // If new profile, passwords must match and can't be null
        if( !m_engine.getManager( AuthenticationManager.class ).isContainerAuthenticated() ) {
            final String password = profile.getPassword();
            if( password == null ) {
                if( isNew ) {
                    session.addMessage( SESSION_MESSAGES, rb.getString( "security.error.blankpassword" ) );
                }
            } else {
                final HttpServletRequest request = context.getHttpRequest();
                final String password2 = ( request == null ) ? null : request.getParameter( "password2" );
                if( !password.equals( password2 ) ) {
                    session.addMessage( SESSION_MESSAGES, rb.getString( "security.error.passwordnomatch" ) );
                }
            }
        }

        UserProfile otherProfile;
        final String fullName = profile.getFullname();
        final String loginName = profile.getLoginName();
        final String email = profile.getEmail();

        // It's illegal to use as a full name someone else's login name
        try {
            otherProfile = getUserDatabase().find( fullName );
            if( otherProfile != null && !profile.equals( otherProfile ) && !fullName.equals( otherProfile.getFullname() ) ) {
                final Object[] args = { fullName };
                session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalfullname" ), args ) );
            }
        } catch( final NoSuchPrincipalException e ) { /* It's clean */ }

        // It's illegal to use as a login name someone else's full name
        try {
            otherProfile = getUserDatabase().find( loginName );
            if( otherProfile != null && !profile.equals( otherProfile ) && !loginName.equals( otherProfile.getLoginName() ) ) {
                final Object[] args = { loginName };
                session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalloginname" ), args ) );
            }
        } catch( final NoSuchPrincipalException e ) { /* It's clean */ }

        // It's illegal to use multiple accounts with the same email
        try {
            otherProfile = getUserDatabase().findByEmail( email );
            if( otherProfile != null && !profile.getUid().equals( otherProfile.getUid() ) // Issue JSPWIKI-1042
                    && !profile.equals( otherProfile ) && StringUtils.lowerCase( email )
                    .equals( StringUtils.lowerCase( otherProfile.getEmail() ) ) ) {
                final Object[] args = { email };
                session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.email.taken" ), args ) );
            }
        } catch( final NoSuchPrincipalException e ) { /* It's clean */ }
    }

    /** {@inheritDoc} */
    @Override
    public Principal[] listWikiNames() throws WikiSecurityException {
        return getUserDatabase().getWikiNames();
    }

    // events processing .......................................................

    /**
     * Registers a WikiEventListener with this instance.
     * This is a convenience method.
     * @param listener the event listener
     */
    @Override public synchronized void addWikiEventListener( final WikiEventListener listener ) {
        WikiEventManager.addWikiEventListener( this, listener );
    }

    /**
     * Un-registers a WikiEventListener with this instance.
     * This is a convenience method.
     * @param listener the event listener
     */
    @Override public synchronized void removeWikiEventListener( final WikiEventListener listener ) {
        WikiEventManager.removeWikiEventListener( this, listener );
    }

    /**
     *  Implements the JSON API for usermanager.
     *  <p>
     *  Even though this gets serialized whenever container shuts down/restarts, this gets reinstalled to the session when JSPWiki starts.
     *  This means that it's not actually necessary to save anything.
     */
    public static final class JSONUserModule implements WikiAjaxServlet {

		private volatile DefaultUserManager m_manager;

        /**
         *  Create a new JSONUserModule.
         *  @param mgr Manager
         */
        public JSONUserModule( final DefaultUserManager mgr )
        {
            m_manager = mgr;
        }

        @Override
        public String getServletMapping() {
        	return JSON_USERS;
        }

        @Override
        public void service( final HttpServletRequest req, final HttpServletResponse resp, final String actionName, final List<String> params) throws ServletException, IOException {
        	try {
            	if( params.size() < 1 ) {
            		return;
            	}
        		final String uid = params.get(0);
	        	log.debug("uid="+uid);
	        	if (StringUtils.isNotBlank(uid)) {
		            final UserProfile prof = getUserInfo(uid);
		            resp.getWriter().write(AjaxUtil.toJson(prof));
	        	}
        	} catch (final NoSuchPrincipalException e) {
        		throw new ServletException(e);
        	}
        }

        /**
         *  Directly returns the UserProfile object attached to an uid.
         *
         *  @param uid The user id (e.g. WikiName)
         *  @return A UserProfile object
         *  @throws NoSuchPrincipalException If such a name does not exist.
         */
        public UserProfile getUserInfo( final String uid ) throws NoSuchPrincipalException {
            if( m_manager != null ) {
                return m_manager.getUserDatabase().find( uid );
            }

            throw new IllegalStateException( "The manager is offline." );
        }
    }

}
