/*
 * 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.directory.server.core.changelog;


import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.directory.api.ldap.model.cursor.Cursor;
import org.apache.directory.api.ldap.model.cursor.ListCursor;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.util.DateUtils;
import org.apache.directory.api.util.TimeProvider;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.LdapPrincipal;
import org.apache.directory.server.core.api.changelog.ChangeLogEvent;
import org.apache.directory.server.core.api.changelog.ChangeLogEventSerializer;
import org.apache.directory.server.core.api.changelog.Tag;
import org.apache.directory.server.core.api.changelog.TaggableChangeLogStore;
import org.apache.directory.server.i18n.I18n;


/**
 * A change log store that keeps it's information in memory.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class MemoryChangeLogStore implements TaggableChangeLogStore
{

    private static final String REV_FILE = "revision";
    private static final String TAG_FILE = "tags";
    private static final String CHANGELOG_FILE = "changelog.dat";

    /** An incremental number giving the current revision */
    private long currentRevision;

    /** The latest tag */
    private Tag latest;

    /** A Map of tags and revisions */
    private final Map<Long, Tag> tags = new HashMap<>( 100 );

    private final List<ChangeLogEvent> events = new ArrayList<>();
    private File workingDirectory;

    /** The DirectoryService */
    private DirectoryService directoryService;

    private TimeProvider timeProvider = TimeProvider.DEFAULT;

    /**
     * {@inheritDoc}
     */
    @Override
    public Tag tag( long revision )
    {
        if ( tags.containsKey( revision ) )
        {
            return tags.get( revision );
        }

        latest = new Tag( revision, null );
        tags.put( revision, latest );
        
        return latest;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Tag tag()
    {
        if ( ( latest != null ) && ( latest.getRevision() == currentRevision ) )
        {
            return latest;
        }

        latest = new Tag( currentRevision, null );
        tags.put( currentRevision, latest );
        return latest;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Tag tag( String description )
    {
        if ( ( latest != null ) && ( latest.getRevision() == currentRevision ) )
        {
            return latest;
        }

        latest = new Tag( currentRevision, description );
        tags.put( currentRevision, latest );
        return latest;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void init( DirectoryService service ) throws LdapException
    {
        workingDirectory = service.getInstanceLayout().getLogDirectory();
        this.directoryService = service;
        this.timeProvider = service.getTimeProvider();
        
        try
        {
            loadRevision();
            loadTags();
            loadChangeLog();
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    private void loadRevision() throws IOException
    {
        File revFile = new File( workingDirectory, REV_FILE );

        if ( revFile.exists() )
        {
            try ( BufferedReader reader = Files.newBufferedReader( revFile.toPath(), StandardCharsets.UTF_8 ) )
            {
                String line = reader.readLine();
                currentRevision = Long.parseLong( line );
            }
        }
    }


    private void saveRevision() throws IOException
    {
        File revFile = new File( workingDirectory, REV_FILE );

        if ( revFile.exists() && !revFile.delete() )
        {
            throw new IOException( I18n.err( I18n.ERR_726_FILE_UNDELETABLE, revFile.getAbsolutePath() ) );
        }

        
        try ( PrintWriter out = new PrintWriter( Files.newBufferedWriter( revFile.toPath(), StandardCharsets.UTF_8 ) ) )
        {
            out.println( currentRevision );
            out.flush();
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    private void saveTags() throws IOException
    {
        File tagFile = new File( workingDirectory, TAG_FILE );

        if ( tagFile.exists() && !tagFile.delete() )
        {
            throw new IOException( I18n.err( I18n.ERR_726_FILE_UNDELETABLE, tagFile.getAbsolutePath() ) );
        }

        OutputStream out = null;

        try
        {
            out = Files.newOutputStream( tagFile.toPath() );

            Properties props = new Properties();

            for ( Tag tag : tags.values() )
            {
                String key = String.valueOf( tag.getRevision() );

                if ( tag.getDescription() == null )
                {
                    props.setProperty( key, "null" );
                }
                else
                {
                    props.setProperty( key, tag.getDescription() );
                }
            }

            props.store( out, null );
            out.flush();
        }
        finally
        {
            if ( out != null )
            {
                out.close();
            }
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    private void loadTags() throws IOException
    {
        File revFile = new File( workingDirectory, REV_FILE );

        if ( revFile.exists() )
        {
            Properties props = new Properties();
            InputStream in = null;

            try
            {
                in = Files.newInputStream( revFile.toPath() );
                props.load( in );
                ArrayList<Long> revList = new ArrayList<>();

                for ( Object key : props.keySet() )
                {
                    revList.add( Long.valueOf( ( String ) key ) );
                }

                Collections.sort( revList );
                Tag tag = null;

                // @todo need some serious syncrhoization here on tags
                tags.clear();

                for ( Long lkey : revList )
                {
                    String rev = String.valueOf( lkey );
                    String desc = props.getProperty( rev );

                    if ( ( desc != null ) && desc.equals( "null" ) )
                    {
                        tag = new Tag( lkey, null );
                    }
                    else
                    {
                        tag = new Tag( lkey, desc );
                    }

                    tags.put( lkey, tag );
                }

                latest = tag;
            }
            finally
            {
                if ( in != null )
                {
                    in.close();
                }
            }
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    private void loadChangeLog() throws IOException
    {
        File file = new File( workingDirectory, CHANGELOG_FILE );

        if ( file.exists() )
        {
            try ( ObjectInputStream in = new ObjectInputStream( Files.newInputStream( file.toPath() ) ) )
            {
                int size = in.readInt();

                ArrayList<ChangeLogEvent> changeLogEvents = new ArrayList<>( size );

                for ( int i = 0; i < size; i++ )
                {
                    ChangeLogEvent event = ChangeLogEventSerializer.deserialize( directoryService.getSchemaManager(),
                        in );
                    event.getCommitterPrincipal().setSchemaManager( directoryService.getSchemaManager() );
                    changeLogEvents.add( event );
                }

                // @todo man o man we need some synchronization later after getting this to work
                this.events.clear();
                this.events.addAll( changeLogEvents );
            }
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    private void saveChangeLog() throws IOException
    {
        File file = new File( workingDirectory, CHANGELOG_FILE );

        if ( file.exists() && !file.delete() )
        {
            throw new IOException( I18n.err( I18n.ERR_726_FILE_UNDELETABLE, file.getAbsolutePath() ) );
        }

        file.createNewFile();

        try ( ObjectOutputStream out = new ObjectOutputStream( Files.newOutputStream( file.toPath() ) ) )
        {
            out.writeInt( events.size() );

            for ( ChangeLogEvent event : events )
            {
                ChangeLogEventSerializer.serialize( event, out );
            }

            out.flush();
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void sync() throws LdapException
    {
        try
        {
            saveRevision();
            saveTags();
            saveChangeLog();
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }
    }


    /**
     * Save logs, tags and revision on disk, and clean everything in memory
     */
    @Override
    public void destroy() throws LdapException
    {
        try
        {
            saveRevision();
            saveTags();
            saveChangeLog();
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public long getCurrentRevision()
    {
        return currentRevision;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ChangeLogEvent log( LdapPrincipal principal, LdifEntry forward, LdifEntry reverse )
    {
        currentRevision++;
        ChangeLogEvent event = new ChangeLogEvent( currentRevision, 
            DateUtils.getGeneralizedTime( directoryService.getTimeProvider() ),
            principal, forward, reverse );
        events.add( event );
        
        return event;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ChangeLogEvent log( LdapPrincipal principal, LdifEntry forward, List<LdifEntry> reverses )
    {
        currentRevision++;
        ChangeLogEvent event = new ChangeLogEvent( currentRevision, 
            DateUtils.getGeneralizedTime( timeProvider ), principal, forward, reverses );
        events.add( event );
        
        return event;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ChangeLogEvent lookup( long revision )
    {
        if ( revision < 0 )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_239 ) );
        }

        if ( revision > getCurrentRevision() )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_240 ) );
        }

        return events.get( ( int ) revision );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Cursor<ChangeLogEvent> find()
    {
        return new ListCursor<>( events );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Cursor<ChangeLogEvent> findBefore( long revision )
    {
        return new ListCursor<>( events, ( int ) revision );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Cursor<ChangeLogEvent> findAfter( long revision )
    {
        return new ListCursor<>( ( int ) revision, events );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Cursor<ChangeLogEvent> find( long startRevision, long endRevision )
    {
        return new ListCursor<>( ( int ) startRevision, events, ( int ) ( endRevision + 1 ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Tag getLatest()
    {
        return latest;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Tag removeTag( long revision )
    {
        return tags.remove( revision );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Tag tag( long revision, String descrition )
    {
        if ( tags.containsKey( revision ) )
        {
            return tags.get( revision );
        }

        latest = new Tag( revision, descrition );
        tags.put( revision, latest );
        return latest;
    }


    /**
     * @see Object#toString()
     */
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();

        sb.append( "MemoryChangeLog\n" );
        sb.append( "latest tag : " ).append( latest ).append( '\n' );

        sb.append( "Nb of events : " ).append( events.size() ).append( '\n' );

        int i = 0;

        for ( ChangeLogEvent event : events )
        {
            sb.append( "event[" ).append( i++ ).append( "] : " );
            sb.append( "\n---------------------------------------\n" );
            sb.append( event );
            sb.append( "\n---------------------------------------\n" );
        }

        return sb.toString();
    }
}
