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


import static org.junit.Assert.assertTrue;

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.asn1.ber.Asn1Decoder;
import org.apache.directory.api.util.Strings;
import org.apache.directory.shared.kerberos.KerberosTime;
import org.apache.directory.shared.kerberos.codec.krbCredInfo.KrbCredInfoContainer;
import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
import org.apache.directory.shared.kerberos.codec.types.PrincipalNameType;
import org.apache.directory.shared.kerberos.components.EncryptionKey;
import org.apache.directory.shared.kerberos.components.HostAddress;
import org.apache.directory.shared.kerberos.components.HostAddresses;
import org.apache.directory.shared.kerberos.components.KrbCredInfo;
import org.apache.directory.shared.kerberos.components.PrincipalName;
import org.apache.directory.shared.kerberos.flags.TicketFlag;
import org.apache.directory.shared.kerberos.flags.TicketFlags;
import org.junit.Before;
import org.junit.Test;


/**
 * Test cases for KrbCredInfo codec.
 *
 * This test class assumes that the encoding of KrbCredInfo class is correct and highly relies on its functionality
 * to generate test PDUs instead of generating them by hand. Also note that the accuracy of this test case depends on
 * the accuracy of the encoding done by the components constituted in KrbCredInfo ASN.1 structure
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class KrbCredInfoDecoderTest
{
    private EncryptionKey key;
    private String pRealm;
    private PrincipalName pName;
    private TicketFlags ticketFlags;
    private KerberosTime authTime;
    private KerberosTime startTime;
    private KerberosTime endTime;
    private KerberosTime renewtill;
    private String sRealm;
    private PrincipalName sName;
    private HostAddresses clientAddresses;

    private List<FieldValueHolder> optionalFieldValueList;

    class FieldValueHolder
    {
        String fieldName;
        Object value;


        FieldValueHolder( String fieldName, Object value )
        {
            this.fieldName = fieldName;
            this.value = value;
        }


        @Override
        public String toString()
        {
            return "FieldValueHolder [fieldName=" + fieldName + ", value=" + value + "]";
        }
    }


    @Before
    public void setup() throws Exception
    {
        optionalFieldValueList = new ArrayList<FieldValueHolder>();

        key = new EncryptionKey( EncryptionType.DES3_CBC_MD5, new byte[]
            { 0, 1 } );

        pRealm = "prealm";
        // NOTE: we have to add each field manually cause order is important
        optionalFieldValueList.add( new FieldValueHolder( "pRealm", pRealm ) );

        ticketFlags = new TicketFlags( TicketFlag.INITIAL.getValue() );
        optionalFieldValueList.add( new FieldValueHolder( "ticketFlags", ticketFlags ) );

        authTime = new KerberosTime( new Date().getTime() );
        optionalFieldValueList.add( new FieldValueHolder( "authTime", authTime ) );

        startTime = new KerberosTime( new Date().getTime() );
        optionalFieldValueList.add( new FieldValueHolder( "startTime", startTime ) );

        endTime = new KerberosTime( new Date().getTime() );
        optionalFieldValueList.add( new FieldValueHolder( "endTime", endTime ) );

        renewtill = new KerberosTime( new Date().getTime() );
        optionalFieldValueList.add( new FieldValueHolder( "renewtill", renewtill ) );

        sRealm = "srealm";
        optionalFieldValueList.add( new FieldValueHolder( "sRealm", sRealm ) );

        pName = new PrincipalName( "pname", PrincipalNameType.KRB_NT_PRINCIPAL );
        optionalFieldValueList.add( new FieldValueHolder( "pName", pName ) );

        sName = new PrincipalName( "sname", PrincipalNameType.KRB_NT_PRINCIPAL );
        optionalFieldValueList.add( new FieldValueHolder( "sName", sName ) );

        clientAddresses = new HostAddresses( new HostAddress[]
            { new HostAddress( InetAddress.getByName( "localhost" ) ) } );
        optionalFieldValueList.add( new FieldValueHolder( "clientAddresses", clientAddresses ) );
    }


    @Test
    public void testKrbCredInfo() throws Exception
    {
        // algorithm:
        // start from the first mandatory element and then add one of the subsequent OPTIONAL elements(in order) then
        // start adding/removing subsequent OPTIONAL elements(those which fall after the above OPTIONAL element)
        // one by one and then test decoding

        int size = optionalFieldValueList.size();

        for ( int i = 0; i < size; i++ )
        {
            KrbCredInfo expected = new KrbCredInfo();
            expected.setKey( key );
            Map<String, Field> krbCredInfoFieldNameMap = getFieldMap( expected );

            List<FieldValueHolder> presentFieldList = new ArrayList<FieldValueHolder>();

            FieldValueHolder fieldValHolder = optionalFieldValueList.get( i );
            presentFieldList.add( fieldValHolder );

            Field f = krbCredInfoFieldNameMap.get( Strings.toLowerCase( fieldValHolder.fieldName ) );
            f.set( expected, fieldValHolder.value );

            for ( int j = i + 1; j < size; j++ )
            {
                fieldValHolder = optionalFieldValueList.get( j );
                presentFieldList.add( fieldValHolder );
                f = krbCredInfoFieldNameMap.get( Strings.toLowerCase( fieldValHolder.fieldName ) );
                f.set( expected, fieldValHolder.value );
            }

            ByteBuffer stream = ByteBuffer.allocate( expected.computeLength() );
            expected.encode( stream );
            stream.flip();

            Asn1Decoder decoder = new Asn1Decoder();
            KrbCredInfoContainer container = new KrbCredInfoContainer();
            container.setStream( stream );

            try
            {
                decoder.decode( stream, container );
            }
            catch ( DecoderException e )
            {
                // NOTE: keep this sysout for easy debugging (no need to setup a logger)
                System.out.println( "failed sequence:\n" + expected );
                throw e;
            }

            KrbCredInfo actual = container.getKrbCredInfo();
            assertValues( presentFieldList, actual );
        }

    }


    @Test
    public void testKrbCredInfoWithEachOptElement() throws Exception
    {
        // algorithm:
        // start from the first mandatory element and add ONLY one OPTIONAL element and then test decoding

        int size = optionalFieldValueList.size();
        for ( int i = size - 1; i >= 0; i-- )
        {
            KrbCredInfo expected = new KrbCredInfo();
            expected.setKey( key );
            Map<String, Field> krbCredInfoFieldNameMap = getFieldMap( expected );

            List<FieldValueHolder> presentFieldList = new ArrayList<FieldValueHolder>();

            FieldValueHolder fieldValHolder = optionalFieldValueList.get( i );
            presentFieldList.add( fieldValHolder );

            Field f = krbCredInfoFieldNameMap.get( Strings.toLowerCase( fieldValHolder.fieldName ) );
            f.set( expected, fieldValHolder.value );

            ByteBuffer stream = ByteBuffer.allocate( expected.computeLength() );
            expected.encode( stream );
            stream.flip();

            Asn1Decoder decoder = new Asn1Decoder();
            KrbCredInfoContainer container = new KrbCredInfoContainer();
            container.setStream( stream );

            try
            {
                decoder.decode( stream, container );
            }
            catch ( DecoderException e )
            {
                // NOTE: keep this sysout for easy debugging (no need to setup a logger)
                System.out.println( "failed sequence:\n" + expected );
                throw e;
            }

            KrbCredInfo actual = container.getKrbCredInfo();
            assertValues( presentFieldList, actual );
        }
    }


    /**
     * compare the values that are inserted into the KrbCredInfo objects before encoding to
     * those that are obtained from decoded KrbCredInfo
     *
     * @param presentFieldList the list of values that were inserted in the KrbCredInfo class before encoding
     * @param decoded the decoded KrbCredInfo object
     */
    private void assertValues( List<FieldValueHolder> presentFieldList, KrbCredInfo decoded ) throws Exception
    {
        Map<String, Field> krbCredInfoFieldNameMap = getFieldMap( decoded );

        for ( FieldValueHolder fh : presentFieldList )
        {
            Field actualField = krbCredInfoFieldNameMap.get( Strings.toLowerCase( fh.fieldName ) );
            Object decodedValue = actualField.get( decoded );

            //System.out.println( fh.fieldName + " expected: " + fh.value + " , actual: " + decodedValue );

            assertTrue( decodedValue.equals( fh.value ) );
        }
    }


    /**
     * create a map with the field's name and field objects of the KrbCreInfo
     *
     * @param source the KrbCredInfo object
     */
    private Map<String, Field> getFieldMap( KrbCredInfo source )
    {
        Field[] fields = source.getClass().getDeclaredFields();

        Map<String, Field> fieldNameMap = new HashMap<String, Field>();

        for ( Field f : fields )
        {
            f.setAccessible( true );
            fieldNameMap.put( Strings.toLowerCase( f.getName() ), f );
        }

        return fieldNameMap;
    }
}
