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

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.apache.oro.text.GlobCompiler;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.wiki.WikiBackgroundThread;
import org.apache.wiki.WikiContext;
import org.apache.wiki.api.core.Context;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Page;
import org.apache.wiki.api.exceptions.PluginException;
import org.apache.wiki.api.plugin.InitializablePlugin;
import org.apache.wiki.api.plugin.Plugin;
import org.apache.wiki.event.WikiEngineEvent;
import org.apache.wiki.event.WikiEvent;
import org.apache.wiki.event.WikiEventListener;
import org.apache.wiki.event.WikiPageEvent;
import org.apache.wiki.event.WikiPageRenameEvent;
import org.apache.wiki.references.ReferenceManager;
import org.apache.wiki.render.RenderingManager;
import org.apache.wiki.util.TextUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.TreeMap;


/**
 * This plugin counts the number of times a page has been viewed.<br/>
 * Parameters:
 * <ul>
 * <li>count=yes|no</li>
 * <li>show=none|count|list</li>
 * <li>entries=maximum number of list entries to be returned</li>
 * <li>min=minimum page count to be listed</li>
 * <li>max=maximum page count to be listed</li>
 * <li>sort=name|count</li>
 * </ul>
 * Default values:<br/>
 * <code>show=none  sort=name</code>
 * 
 * @since 2.8
 */
public class PageViewPlugin extends AbstractReferralPlugin implements Plugin, InitializablePlugin {

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

    /** The page view manager. */
    private static PageViewManager c_singleton = null;

    /** Constant for the 'count' parameter / value. */
    private static final String PARAM_COUNT = "count";

    /** Name of the 'entries' parameter. */
    private static final String PARAM_MAX_ENTRIES = "entries";

    /** Name of the 'max' parameter. */
    private static final String PARAM_MAX_COUNT = "max";

    /** Name of the 'min' parameter. */
    private static final String PARAM_MIN_COUNT = "min";

    /** Name of the 'refer' parameter. */
    private static final String PARAM_REFER = "refer";

    /** Name of the 'sort' parameter. */
    private static final String PARAM_SORT = "sort";

    /** Constant for the 'none' parameter value. */
    private static final String STR_NONE = "none";

    /** Constant for the 'list' parameter value. */
    private static final String STR_LIST = "list";

    /** Constant for the 'yes' parameter value. */
    private static final String STR_YES = "yes";

    /** Constant for empty string. */
    private static final String STR_EMPTY = "";

    /** Constant for Wiki markup separator. */
    private static final String STR_SEPARATOR = "----";

    /** Constant for comma-separated list separator. */
    private static final String STR_COMMA = ",";

    /** Constant for no-op glob expression. */
    private static final String STR_GLOBSTAR = "*";

    /** Constant for file storage. */
    private static final String COUNTER_PAGE = "PageCount.txt";

    /** Constant for storage interval in seconds. */
    private static final int STORAGE_INTERVAL = 60;

    /**
     * Initialize the PageViewPlugin and its singleton.
     * 
     * @param engine The wiki engine.
     */
    @Override
    public void initialize( final Engine engine ) {
        log.info( "initializing PageViewPlugin" );
        synchronized( this ) {
            if( c_singleton == null ) {
                c_singleton = new PageViewManager();
            }
            c_singleton.initialize( engine );
        }
    }

    /**
     * Cleanup the singleton reference.
     */
    private void cleanup() {
        log.info( "cleaning up PageView Manager" );
        c_singleton = null;
    }

    /**
     *  {@inheritDoc}
     */
    @Override
    public String execute( final Context context, final Map< String, String > params ) throws PluginException {
        final PageViewManager manager = c_singleton;
        String result = STR_EMPTY;

        if( manager != null ) {
            result = manager.execute( context, params );
        }

        return result;
    }

    /**
     * Page view manager, handling all storage.
     */
    public final class PageViewManager implements WikiEventListener {
        /** Are we initialized? */
        private boolean m_initialized = false;

        /** The page counters. */
        private Map<String, Counter> m_counters = null;

        /** The page counters in storage format. */
        private Properties m_storage = null;

        /** Are all changes stored? */
        private boolean m_dirty = false;

        /** The page count storage background thread. */
        private Thread m_pageCountSaveThread = null;

        /** The work directory. */
        private String m_workDir = null;

        /** Comparator for descending sort on page count. */
        private final Comparator< Object > m_compareCountDescending = ( o1, o2 ) -> {
            final int v1 = getCount( o1 );
            final int v2 = getCount( o2 );
            return ( v1 == v2 ) ? ( ( String )o1 ).compareTo( ( String )o2 ) : ( v1 < v2 ) ? 1 : -1;
        };

        /**
         * Initialize the page view manager.
         * 
         * @param engine The wiki engine.
         */
        public synchronized void initialize( final Engine engine ) {
            log.info( "initializing PageView Manager" );
            m_workDir = engine.getWorkDir();
            engine.addWikiEventListener( this );
            if( m_counters == null ) {
                // Load the counters into a collection
                m_storage = new Properties();
                m_counters = new TreeMap<>();

                loadCounters();
            }

            // backup counters every 5 minutes
            if( m_pageCountSaveThread == null ) {
                m_pageCountSaveThread = new CounterSaveThread( engine, 5 * STORAGE_INTERVAL, this );
                m_pageCountSaveThread.start();
            }

            m_initialized = true;
        }

        /**
         * Handle the shutdown event via the page counter thread.
         */
        private synchronized void handleShutdown() {
            log.info( "handleShutdown: The counter store thread was shut down." );

            cleanup();

            if( m_counters != null ) {

                m_dirty = true;
                storeCounters();

                m_counters.clear();
                m_counters = null;

                m_storage.clear();
                m_storage = null;
            }

            m_initialized = false;

            m_pageCountSaveThread = null;
        }

        /**
         * Inspect wiki events for shutdown.
         * 
         * @param event The wiki event to inspect.
         */
        @Override
        public void actionPerformed( final WikiEvent event ) {
            if( event instanceof WikiEngineEvent ) {
                if( event.getType() == WikiEngineEvent.SHUTDOWN ) {
                    log.info( "Detected wiki engine shutdown" );
                    handleShutdown();
                }
            } else if( ( event instanceof WikiPageRenameEvent ) && ( event.getType() == WikiPageRenameEvent.PAGE_RENAMED ) ) {
                final String oldPageName = ( ( WikiPageRenameEvent )event ).getOldPageName();
                final String newPageName = ( ( WikiPageRenameEvent )event ).getNewPageName();
                final Counter oldCounter = m_counters.get( oldPageName );
                if( oldCounter != null ) {
                    m_storage.remove( oldPageName );
                    m_counters.put( newPageName, oldCounter );
                    m_storage.setProperty( newPageName, oldCounter.toString() );
                    m_counters.remove( oldPageName );
                    m_dirty = true;
                }
            } else if( ( event instanceof WikiPageEvent ) && ( event.getType() == WikiPageEvent.PAGE_DELETED ) ) {
                final String pageName = ( ( WikiPageEvent )event ).getPageName();
                m_storage.remove( pageName );
                m_counters.remove( pageName );
            }
        }

        /**
         * Count a page hit, present a pages' counter or output a list of page counts.
         * 
         * @param context the wiki context
         * @param params the plugin parameters
         * @return String Wiki page snippet
         * @throws PluginException Malformed pattern parameter.
         */
        public String execute( final Context context, final Map< String, String > params ) throws PluginException {
            final Engine engine = context.getEngine();
            final Page page = context.getPage();
            String result = STR_EMPTY;

            if( page != null ) {
                // get parameters
                final String pagename = page.getName();
                String count = params.get( PARAM_COUNT );
                final String show = params.get( PARAM_SHOW );
                int entries = TextUtil.parseIntParameter( params.get( PARAM_MAX_ENTRIES ), Integer.MAX_VALUE );
                final int max = TextUtil.parseIntParameter( params.get( PARAM_MAX_COUNT ), Integer.MAX_VALUE );
                final int min = TextUtil.parseIntParameter( params.get( PARAM_MIN_COUNT ), Integer.MIN_VALUE );
                final String sort = params.get( PARAM_SORT );
                final String body = params.get( DefaultPluginManager.PARAM_BODY );
                final Pattern[] exclude = compileGlobs( PARAM_EXCLUDE, params.get( PARAM_EXCLUDE ) );
                final Pattern[] include = compileGlobs( PARAM_INCLUDE, params.get( PARAM_INCLUDE ) );
                final Pattern[] refer = compileGlobs( PARAM_REFER, params.get( PARAM_REFER ) );
                final PatternMatcher matcher = (null != exclude || null != include || null != refer) ? new Perl5Matcher() : null;
                boolean increment = false;

                // increment counter?
                if( STR_YES.equals( count ) ) {
                    increment = true;
                } else {
                    count = null;
                }

                // default increment counter?
                if( ( show == null || STR_NONE.equals( show ) ) && count == null ) {
                    increment = true;
                }

                // filter on referring pages?
                Collection< String > referrers = null;

                if( refer != null ) {
                    final ReferenceManager refManager = engine.getManager( ReferenceManager.class );
                    for( final String name : refManager.findCreated() ) {
                        boolean use = false;
                        for( int n = 0; !use && n < refer.length; n++ ) {
                            use = matcher.matches( name, refer[ n ] );
                        }

                        if( use ) {
                            final Collection< String > refs = engine.getManager( ReferenceManager.class ).findReferrers( name );
                            if( refs != null && !refs.isEmpty() ) {
                                if( referrers == null ) {
                                    referrers = new HashSet<>();
                                }
                                referrers.addAll( refs );
                            }
                        }
                    }
                }

                synchronized( this ) {
                    Counter counter = m_counters.get( pagename );

                    // only count in view mode, keep storage values in sync
                    if( increment && WikiContext.VIEW.equalsIgnoreCase( context.getRequestContext() ) ) {
                        if( counter == null ) {
                            counter = new Counter();
                            m_counters.put( pagename, counter );
                        }
                        counter.increment();
                        m_storage.setProperty( pagename, counter.toString() );
                        m_dirty = true;
                    }

                    if( show == null || STR_NONE.equals( show ) ) {
                        // nothing to show

                    } else if( PARAM_COUNT.equals( show ) ) {
                        // show page count
                        if( counter == null ) {
                            counter = new Counter();
                            m_counters.put( pagename, counter );
                            m_storage.setProperty( pagename, counter.toString() );
                            m_dirty = true;
                        }
                        result = counter.toString();

                    } else if( body != null && 0 < body.length() && STR_LIST.equals( show ) ) {
                        // show list of counts
                        String header = STR_EMPTY;
                        String line = body;
                        String footer = STR_EMPTY;
                        int start = body.indexOf( STR_SEPARATOR );

                        // split body into header, line, footer on ---- separator
                        if( 0 < start ) {
                            header = body.substring( 0, start );
                            start = skipWhitespace( start + STR_SEPARATOR.length(), body );
                            int end = body.indexOf( STR_SEPARATOR, start );
                            if( start >= end ) {
                                line = body.substring( start );
                            } else {
                                line = body.substring( start, end );
                                end = skipWhitespace( end + STR_SEPARATOR.length(), body );
                                footer = body.substring( end );
                            }
                        }

                        // sort on name or count?
                        Map< String, Counter > sorted = m_counters;
                        if( PARAM_COUNT.equals( sort ) ) {
                            sorted = new TreeMap<>( m_compareCountDescending );
                            sorted.putAll( m_counters );
                        }

                        // build a messagebuffer with the list in wiki markup
                        final StringBuffer buf = new StringBuffer( header );
                        final MessageFormat fmt = new MessageFormat( line );
                        final Object[] args = new Object[] { pagename, STR_EMPTY, STR_EMPTY };
                        final Iterator< Entry< String, Counter > > iter = sorted.entrySet().iterator();

                        while( 0 < entries && iter.hasNext() ) {
                            final Entry< String, Counter > entry = iter.next();
                            final String name = entry.getKey();

                            // check minimum/maximum count
                            final int value = entry.getValue().getValue();
                            boolean use = min <= value && value <= max;

                            // did we specify a refer-to page?
                            if( use && referrers != null ) {
                                use = referrers.contains( name );
                            }

                            // did we specify what pages to include?
                            if( use && include != null ) {
                                use = false;

                                for( int n = 0; !use && n < include.length; n++ ) {
                                    use = matcher.matches( name, include[ n ] );
                                }
                            }

                            // did we specify what pages to exclude?
                            if( use && null != exclude ) {
                                for( int n = 0; use && n < exclude.length; n++ ) {
                                    use &= !matcher.matches( name, exclude[ n ] );
                                }
                            }

                            if( use ) {
                                args[ 1 ] = engine.getManager( RenderingManager.class ).beautifyTitle( name );
                                args[ 2 ] = entry.getValue();

                                fmt.format( args, buf, null );

                                entries--;
                            }
                        }
                        buf.append( footer );

                        // let the engine render the list
                        result = engine.getManager( RenderingManager.class ).textToHTML( context, buf.toString() );
                    }
                }
            }
            return result;
        }

        /**
         * Compile regexp parameter.
         * 
         * @param name The name of the parameter.
         * @param value The parameter value.
         * @return Pattern[] The compiled patterns, or <code>null</code>.
         * @throws PluginException On malformed patterns.
         */
        private Pattern[] compileGlobs( final String name, final String value ) throws PluginException {
            Pattern[] result = null;
            if( value != null && 0 < value.length() && !STR_GLOBSTAR.equals( value ) ) {
                try {
                    final PatternCompiler pc = new GlobCompiler();
                    final String[] ptrns = StringUtils.split( value, STR_COMMA );
                    result = new Pattern[ ptrns.length ];

                    for( int n = 0; n < ptrns.length; n++ ) {
                        result[ n ] = pc.compile( ptrns[ n ] );
                    }
                } catch( final MalformedPatternException e ) {
                    throw new PluginException( "Parameter " + name + " has a malformed pattern: " + e.getMessage() );
                }
            }

            return result;
        }

        /**
         * Adjust offset skipping whitespace.
         * 
         * @param offset The offset in value to adjust.
         * @param value String in which offset points.
         * @return int Adjusted offset into value.
         */
        private int skipWhitespace( int offset, final String value ) {
            while( Character.isWhitespace( value.charAt( offset ) ) ) {
                offset++;
            }
            return offset;
        }

        /**
         * Retrieve a page count.
         * 
         * @return int The page count for the given key.
         * @param key the key for the Counter
         */
        protected int getCount( final Object key )
        {
            return m_counters.get( key ).getValue();
        }

        /**
         * Load the page view counters from file.
         */
        private void loadCounters() {
            if( m_counters != null && m_storage != null ) {
                log.info( "Loading counters." );
                synchronized( this ) {
                    try( final InputStream fis = new FileInputStream( new File( m_workDir, COUNTER_PAGE ) ) ) {
                        m_storage.load( fis );
                    } catch( final IOException ioe ) {
                        log.error( "Can't load page counter store: " + ioe.getMessage() + " , will create a new one!" );
                    }

                    // Copy the collection into a sorted map
                    for( final Entry< ?, ? > entry : m_storage.entrySet() ) {
                        m_counters.put( ( String )entry.getKey(), new Counter( ( String )entry.getValue() ) );
                    }
                    
                    log.info( "Loaded " + m_counters.size() + " counter values." );
                }
            }
        }

        /**
         * Save the page view counters to file.
         */
        protected void storeCounters() {
            if( m_counters != null && m_storage != null && m_dirty ) {
                log.info( "Storing " + m_counters.size() + " counter values." );
                synchronized( this ) {
                    // Write out the collection of counters
                    try( final OutputStream fos = new FileOutputStream( new File( m_workDir, COUNTER_PAGE ) ) ) {
                        m_storage.store( fos, "\n# The number of times each page has been viewed.\n# Do not modify.\n" );
                        fos.flush();

                        m_dirty = false;
                    } catch( final IOException ioe ) {
                        log.error( "Couldn't store counters values: " + ioe.getMessage() );
                    }
                }
            }
        }

        /**
         * Is the given thread still current?
         *
         * @param thrd thread that can be the current background thread.
         * @return boolean <code>true</code> if the thread is still the current background thread.
         */
        private synchronized boolean isRunning( final Thread thrd )
        {
            return m_initialized && thrd == m_pageCountSaveThread;
        }

    }

    /** Counter for page hits collection. */
    private static final class Counter {

        /** The count value. */
        private int m_count = 0;

        /**
         * Create a new counter.
         */
        public Counter() {
        }

        /**
         * Create and initialize a new counter.
         * 
         * @param value Count value.
         */
        public Counter( final String value )
        {
            setValue( value );
        }

        /**
         * Increment counter.
         */
        public void increment()
        {
            m_count++;
        }

        /**
         * Get the count value.
         * 
         * @return int
         */
        public int getValue()
        {
            return m_count;
        }

        /**
         * Set the count value.
         * 
         * @param value String representation of the count.
         */
        public void setValue( final String value )
        {
            m_count = NumberUtils.toInt( value );
        }

        /**
         * @return String String representation of the count.
         */
        @Override
        public String toString()
        {
            return String.valueOf( m_count );
        }

    }

    /**
     * Background thread storing the page counters.
     */
    static final class CounterSaveThread extends WikiBackgroundThread {

        /** The page view manager. */
        private final PageViewManager m_manager;

        /**
         * Create a wiki background thread to store the page counters.
         * 
         * @param engine The wiki engine.
         * @param interval Delay in seconds between saves.
         * @param pageViewManager page view manager.
         */
        public CounterSaveThread( final Engine engine, final int interval, final PageViewManager pageViewManager ) {
            super( engine, interval );
            if( pageViewManager == null ) {
                throw new IllegalArgumentException( "Manager cannot be null" );
            }

            m_manager = pageViewManager;
        }

        /**
         * Save the page counters to file.
         */
        @Override
        public void backgroundTask() {
            if( m_manager.isRunning( this ) ) {
                m_manager.storeCounters();
            }
        }
    }
}
