/*
 *  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.shared.ldap.extras.controls.syncrepl_impl;


import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import org.apache.directory.shared.asn1.Asn1Object;
import org.apache.directory.shared.asn1.DecoderException;
import org.apache.directory.shared.asn1.EncoderException;
import org.apache.directory.shared.asn1.ber.Asn1Decoder;
import org.apache.directory.shared.asn1.ber.tlv.TLV;
import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
import org.apache.directory.shared.asn1.ber.tlv.Value;
import org.apache.directory.shared.i18n.I18n;
import org.apache.directory.shared.ldap.codec.api.LdapCodecService;
import org.apache.directory.shared.ldap.codec.controls.ControlDecorator;
import org.apache.directory.shared.ldap.extras.controls.SyncInfoValue;
import org.apache.directory.shared.ldap.extras.controls.SyncInfoValueImpl;
import org.apache.directory.shared.ldap.extras.controls.SynchronizationInfoEnum;
import org.apache.directory.shared.util.Strings;


/**
 * A syncInfoValue object, as defined in RFC 4533
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class SyncInfoValueDecorator extends ControlDecorator<SyncInfoValue> implements SyncInfoValue
{
    /** The syncUUIDs cumulative length */
    private int syncUUIDsLength;

    /** An instance of this decoder */
    private static final Asn1Decoder decoder = new Asn1Decoder();


    /**
     * The constructor for this codec. Dont't forget to set the type.
     */
    public SyncInfoValueDecorator( LdapCodecService codec )
    {
        super( codec, new SyncInfoValueImpl() );
    }


    /**
     * The constructor for this codec. Dont't forget to set the type.
     */
    public SyncInfoValueDecorator( LdapCodecService codec, SyncInfoValue control )
    {
        super( codec, control );
    }


    /**
     * The constructor for this codec.
     * @param type The kind of syncInfo we will store. Can be newCookie,
     * refreshPresent, refreshDelete or syncIdSet
     */
    public SyncInfoValueDecorator( LdapCodecService codec, SynchronizationInfoEnum type )
    {
        this( codec );

        setType( type);
    }


    /** The global length for this control */
    private int syncInfoValueLength;

    /**
     * {@inheritDoc}
     */
    public SynchronizationInfoEnum getType()
    {
        return getDecorated().getType();
    }


    /**
     * {@inheritDoc}
     */
    public void setType( SynchronizationInfoEnum type )
    {
        this.getDecorated().setType( type );

        // Initialize the arrayList if needed
        if ( ( type == SynchronizationInfoEnum.SYNC_ID_SET ) && ( getDecorated().getSyncUUIDs() == null ) )
        {
            getDecorated().setSyncUUIDs( new ArrayList<byte[]>() );
        }
    }


    /**
     * {@inheritDoc}
     */
    public byte[] getCookie()
    {
        return getDecorated().getCookie();
    }


    /**
     * {@inheritDoc}
     */
    public void setCookie( byte[] cookie )
    {
        // Copy the bytes
        if ( !Strings.isEmpty( cookie ) )
        {
            byte[] copy = new byte[cookie.length];
            System.arraycopy( cookie, 0, copy, 0, cookie.length );
            getDecorated().setCookie( copy );
        }
        else
        {
            getDecorated().setCookie( null );
        }
    }


    /**
     * {@inheritDoc}
     */
    public boolean isRefreshDone()
    {
        return getDecorated().isRefreshDone();
    }


    /**
     * {@inheritDoc}
     */
    public void setRefreshDone( boolean refreshDone )
    {
        getDecorated().setRefreshDone( refreshDone );
    }


    /**
     * {@inheritDoc}
     */
    public boolean isRefreshDeletes()
    {
        return getDecorated().isRefreshDeletes();
    }


    /**
     * {@inheritDoc}
     */
    public void setRefreshDeletes( boolean refreshDeletes )
    {
        getDecorated().setRefreshDeletes( refreshDeletes );
    }


    /**
     * {@inheritDoc}
     */
    public List<byte[]> getSyncUUIDs()
    {
        return getDecorated().getSyncUUIDs();
    }


    /**
     * {@inheritDoc}
     */
    public void setSyncUUIDs( List<byte[]> syncUUIDs )
    {
        getDecorated().setSyncUUIDs( syncUUIDs );
    }


    /**
     * {@inheritDoc}
     */
    public void addSyncUUID( byte[] syncUUID )
    {
        getDecorated().addSyncUUID( syncUUID );
    }


    /**
     * Compute the SyncInfoValue length.
     *
     * SyncInfoValue :
     *
     * 0xA0 L1 abcd                   // newCookie
     * 0xA1 L2                        // refreshDelete
     *   |
     *  [+--> 0x04 L3 abcd]           // cookie
     *  [+--> 0x01 0x01 (0x00|0xFF)   // refreshDone
     * 0xA2 L4                        // refreshPresent
     *   |
     *  [+--> 0x04 L5 abcd]           // cookie
     *  [+--> 0x01 0x01 (0x00|0xFF)   // refreshDone
     * 0xA3 L6                        // syncIdSet
     *   |
     *  [+--> 0x04 L7 abcd]           // cookie
     *  [+--> 0x01 0x01 (0x00|0xFF)   // refreshDeletes
     *   +--> 0x31 L8                 // SET OF syncUUIDs
     *          |
     *         [+--> 0x04 L9 abcd]    // syncUUID    public static final int AND_FILTER_TAG = 0xA0;

    public static final int OR_FILTER_TAG = 0xA1;

    public static final int NOT_FILTER_TAG = 0xA2;

    public static final int BIND_REQUEST_SASL_TAG = 0xA3;

     */
    @Override
    public int computeLength()
    {
        // The mode length
        syncInfoValueLength = 0;

        switch ( getType() )
        {
            case NEW_COOKIE :
                if ( getCookie() != null )
                {
                    syncInfoValueLength = 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length;
                }
                else
                {
                    syncInfoValueLength = 1 + 1;
                }

                valueLength = syncInfoValueLength;

                // Call the super class to compute the global control length
                return valueLength;

            case REFRESH_DELETE :
            case REFRESH_PRESENT :
                if ( getCookie() != null )
                {
                    syncInfoValueLength = 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length;
                }

                // The refreshDone flag, only if not true, as it default to true
                if ( ! isRefreshDone() )
                {
                    syncInfoValueLength += 1 + 1 + 1;
                }

                valueLength = 1 + TLV.getNbBytes( syncInfoValueLength ) + syncInfoValueLength;

                // Call the super class to compute the global control length
                return valueLength;

            case SYNC_ID_SET :
                if ( getCookie() != null )
                {
                    syncInfoValueLength = 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length;
                }

                // The refreshDeletes flag, default to false
                if ( isRefreshDeletes() )
                {
                    syncInfoValueLength += 1 + 1 + 1;
                }

                // The syncUUIDs if any
                syncUUIDsLength = 0;

                if ( getSyncUUIDs().size() != 0 )
                {
                    for ( byte[] syncUUID: getSyncUUIDs() )
                    {
                        int uuidLength = 1 + TLV.getNbBytes( syncUUID.length ) + syncUUID.length;

                        syncUUIDsLength += uuidLength;
                    }
                }

                syncInfoValueLength += 1 + TLV.getNbBytes( syncUUIDsLength ) + syncUUIDsLength;
                valueLength = 1 + TLV.getNbBytes( syncInfoValueLength ) + syncInfoValueLength;

                // Call the super class to compute the global control length
                return valueLength;

            default :

        }

        return 1 + TLV.getNbBytes( syncInfoValueLength ) + syncInfoValueLength;
    }


    /**
     * Encode the SyncInfoValue control
     *
     * @param buffer The encoded sink
     * @return A ByteBuffer that contains the encoded PDU
     * @throws EncoderException If anything goes wrong.
     */
    @Override
    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
    {
        if ( buffer == null )
        {
            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
        }

        switch ( getType() )
        {
            case NEW_COOKIE :
                // The first case : newCookie
                buffer.put( (byte)SyncInfoValueTags.NEW_COOKIE_TAG.getValue() );

                // As the OCTET_STRING is absorbed by the Application tag,
                // we have to store the L and V separately
                if ( ( getCookie() == null ) || ( getCookie().length == 0 ) )
                {
                    buffer.put( ( byte ) 0 );
                }
                else
                {
                    buffer.put( TLV.getBytes( getCookie().length ) );
                    buffer.put( getCookie() );
                }

                break;

            case REFRESH_DELETE :
                // The second case : refreshDelete
                buffer.put( (byte)SyncInfoValueTags.REFRESH_DELETE_TAG.getValue() );
                buffer.put( TLV.getBytes( syncInfoValueLength ) );

                // The cookie, if any
                if ( getCookie() != null )
                {
                    Value.encode( buffer, getCookie() );
                }

                // The refreshDone flag
                if ( ! isRefreshDone() )
                {
                    Value.encode( buffer, isRefreshDone() );
                }

                break;

            case REFRESH_PRESENT :
                // The third case : refreshPresent
                buffer.put( (byte)SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue() );
                buffer.put( TLV.getBytes( syncInfoValueLength ) );

                // The cookie, if any
                if ( getCookie() != null )
                {
                    Value.encode( buffer, getCookie() );
                }

                // The refreshDone flag
                if ( ! isRefreshDone() )
                {
                    Value.encode( buffer, isRefreshDone() );
                }

                break;

            case SYNC_ID_SET :
                // The last case : syncIdSet
                buffer.put( (byte)SyncInfoValueTags.SYNC_ID_SET_TAG.getValue() );
                buffer.put( TLV.getBytes( syncInfoValueLength ) );

                // The cookie, if any
                if ( getCookie() != null )
                {
                    Value.encode( buffer, getCookie() );
                }

                // The refreshDeletes flag if not false
                if ( isRefreshDeletes() )
                {
                    Value.encode( buffer, isRefreshDeletes() );
                }

                // The syncUUIDs
                buffer.put( UniversalTag.SET.getValue() );
                buffer.put( TLV.getBytes( syncUUIDsLength ) );

                // Loop on the UUIDs if any
                if ( getSyncUUIDs().size() != 0 )
                {
                    for ( byte[] syncUUID: getSyncUUIDs() )
                    {
                        Value.encode( buffer , syncUUID );
                    }
                }
        }

        return buffer;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] getValue()
    {
        if ( value == null )
        {
            try
            {
                computeLength();
                ByteBuffer buffer = ByteBuffer.allocate( valueLength );

                switch ( getType() )
                {
                    case NEW_COOKIE :
                        // The first case : newCookie
                        buffer.put( ( byte ) SyncInfoValueTags.NEW_COOKIE_TAG.getValue() );

                        // As the OCTET_STRING is absorbed by the Application tag,
                        // we have to store the L and V separately
                        if ( ( getCookie() == null ) || ( getCookie().length == 0 ) )
                        {
                            buffer.put( ( byte ) 0 );
                        }
                        else
                        {
                            buffer.put( TLV.getBytes( getCookie().length ) );
                            buffer.put( getCookie() );
                        }

                        break;

                    case REFRESH_DELETE :
                        // The second case : refreshDelete
                        buffer.put( (byte)SyncInfoValueTags.REFRESH_DELETE_TAG.getValue() );
                        buffer.put( TLV.getBytes( syncInfoValueLength ) );

                        // The cookie, if any
                        if ( getCookie() != null )
                        {
                            Value.encode( buffer, getCookie() );
                        }

                        // The refreshDone flag
                        if ( ! isRefreshDone() )
                        {
                            Value.encode( buffer, isRefreshDone() );
                        }

                        break;

                    case REFRESH_PRESENT :
                        // The third case : refreshPresent
                        buffer.put( (byte)SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue() );
                        buffer.put( TLV.getBytes( syncInfoValueLength ) );

                        // The cookie, if any
                        if ( getCookie() != null )
                        {
                            Value.encode( buffer, getCookie() );
                        }

                        // The refreshDone flag
                        if ( ! isRefreshDone() )
                        {
                            Value.encode( buffer, isRefreshDone() );
                        }

                        break;

                    case SYNC_ID_SET :
                        // The last case : syncIdSet
                        buffer.put( (byte)SyncInfoValueTags.SYNC_ID_SET_TAG.getValue() );
                        buffer.put( TLV.getBytes( syncInfoValueLength ) );

                        // The cookie, if any
                        if ( getCookie() != null )
                        {
                            Value.encode( buffer, getCookie() );
                        }

                        // The refreshDeletes flag if not false
                        if ( isRefreshDeletes() )
                        {
                            Value.encode( buffer, isRefreshDeletes() );
                        }

                        // The syncUUIDs
                        buffer.put( UniversalTag.SET.getValue() );
                        buffer.put( TLV.getBytes( syncUUIDsLength ) );

                        // Loop on the UUIDs if any
                        if ( getSyncUUIDs().size() != 0 )
                        {
                            for ( byte[] syncUUID: getSyncUUIDs() )
                            {
                                Value.encode( buffer , syncUUID );
                            }
                        }
                }

                value = buffer.array();
            }
            catch ( Exception e )
            {
                return null;
            }
        }

        return value;
    }


    /**
     * {@inheritDoc}
     */
    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
    {
        ByteBuffer bb = ByteBuffer.wrap( controlBytes );
        SyncInfoValueContainer container = new SyncInfoValueContainer( getCodecService(), this );
        decoder.decode( bb, container );
        return this;
    }
}
