/*
 *   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.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.Network;
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( Network.LOOPBACK ) } );
        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.toLowerCaseAscii( 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.toLowerCaseAscii( fieldValHolder.fieldName ) );
                f.set( expected, fieldValHolder.value );
            }

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

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

            try
            {
                Asn1Decoder.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.toLowerCaseAscii( fieldValHolder.fieldName ) );
            f.set( expected, fieldValHolder.value );

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

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

            try
            {
                Asn1Decoder.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.toLowerCaseAscii( 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.toLowerCaseAscii( f.getName() ), f );
        }

        return fieldNameMap;
    }
}
