/*
 *  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
 *  
 *    https://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.api.ldap.model.entry;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
import org.apache.directory.api.ldap.model.schema.comparators.StringComparator;
import org.apache.directory.api.ldap.model.schema.normalizers.DeepTrimToLowerNormalizer;
import org.apache.directory.api.ldap.model.schema.normalizers.NoOpNormalizer;
import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OctetStringSyntaxChecker;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;


/**
 * Tests that the Value class works properly as expected.
 *
 * Some notes while conducting tests:
 *
 * <ul>
 *   <li>comparing values with different types - how does this behave</li>
 *   <li>exposing access to at from value or to a comparator?</li>
 * </ul>
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@Execution(ExecutionMode.CONCURRENT)
public class StringValueAttributeTypeTest
{
    private EntryUtils.S s;
    private EntryUtils.AT at;
    private EntryUtils.MR mr;


    /**
     * Initialize an AttributeType and the associated MatchingRule 
     * and Syntax
     */
    @BeforeEach
    public void initAT()
    {
        s = new EntryUtils.S( "1.1.1.1", true );
        s.setSyntaxChecker( OctetStringSyntaxChecker.INSTANCE );
        mr = new EntryUtils.MR( "1.1.2.1" );
        mr.setSyntax( s );
        mr.setLdapComparator( new StringComparator( "1.1.2.1" ) );
        mr.setNormalizer( new DeepTrimToLowerNormalizer( "1.1.2.1" ) );
        at = new EntryUtils.AT( "1.1.3.1" );
        at.setEquality( mr );
        at.setOrdering( mr );
        at.setSubstring( mr );
        at.setSyntax( s );
    }


    /**
     * Serialize a Value
     */
    private ByteArrayOutputStream serializeValue( Value value ) throws IOException
    {
        ObjectOutputStream oOut = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try
        {
            oOut = new ObjectOutputStream( out );
            value.writeExternal( oOut );
        }
        catch ( IOException ioe )
        {
            throw ioe;
        }
        finally
        {
            try
            {
                if ( oOut != null )
                {
                    oOut.flush();
                    oOut.close();
                }
            }
            catch ( IOException ioe )
            {
                throw ioe;
            }
        }

        return out;
    }


    /**
     * Deserialize a Value
     */
    private Value deserializeValue( ByteArrayOutputStream out ) throws IOException, ClassNotFoundException
    {
        ObjectInputStream oIn = null;
        ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );

        try
        {
            oIn = new ObjectInputStream( in );

            Value value = Value.createValue( at );

            value.readExternal( oIn );

            return value;
        }
        catch ( IOException ioe )
        {
            throw ioe;
        }
        finally
        {
            try
            {
                if ( oIn != null )
                {
                    oIn.close();
                }
            }
            catch ( IOException ioe )
            {
                throw ioe;
            }
        }
    }


    /**
     * Test the constructor with a null value
     */
    @Test
    public void testClientStringValueNullValue() throws LdapInvalidAttributeValueException
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();

        Value value = new Value( attribute, (String)null );

        assertNull( value.getString() );
        assertTrue( value.isNull() );
    }


    /**
     * Test the getNormValue method
     */
    @Test
    public void testGetNormalizedValue() throws LdapInvalidAttributeValueException
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();

        Value sv = new Value( attribute, (String)null );

        assertTrue( sv.isSchemaAware() );
        assertNull( sv.getString() );
        assertTrue( sv.isSchemaAware() );

        sv = new Value( attribute, "" );
        assertTrue( sv.isSchemaAware() );
        assertEquals( 0, sv.compareTo( "  " ) );
        assertTrue( sv.isSchemaAware() );

        sv = new Value( attribute, "TEST" );
        assertTrue( sv.isSchemaAware() );
        assertEquals( 0, sv.compareTo( " test " ) );
    }


    /**
     * Test the isValid method
     * 
     * The SyntaxChecker does not accept values longer than 5 chars.
     */
    @Test
    public void testIsValid() throws LdapInvalidAttributeValueException
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();

        new Value( attribute, (String)null );
        new Value( attribute, "" );
        new Value( attribute, "TEST" );

        try
        {
            new Value( attribute, "testlong" );
            fail();
        }
        catch ( LdapInvalidAttributeValueException liave )
        {
            assertTrue( true );
        }
    }


    /**
     * Test the normalize method
     */
    @Test
    public void testApply() throws LdapException
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();
        Value sv = Value.createValue( attribute );

        sv = new Value( at, sv );
        assertEquals( 0, sv.compareTo( ( String ) null ) );

        sv = new Value( attribute, "" );
        sv = new Value( at, sv );
        assertEquals( 0, sv.compareTo( "  " ) );

        sv = new Value( attribute, "  A   TEST  " );
        assertEquals( 0, sv.compareTo( " a  test " ) );
    }


    /**
     * Test the instanceOf method
     */
    @Test
    public void testInstanceOf() throws LdapException
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();
        Value ssv = Value.createValue( attribute );

        assertTrue( ssv.isInstanceOf( attribute ) );

        attribute = EntryUtils.getBytesAttributeType();

        assertFalse( ssv.isInstanceOf( attribute ) );
    }


    /**
     * Test the getAttributeType method
     */
    @Test
    public void testgetAttributeType()
    {
        AttributeType attribute = EntryUtils.getIA5StringAttributeType();
        Value ssv = Value.createValue( attribute );

        assertEquals( attribute, ssv.getAttributeType() );
    }


    /**
     * Test the equals method
     */
    @Test
    public void testEquals() throws LdapInvalidAttributeValueException
    {
        AttributeType at1 = EntryUtils.getIA5StringAttributeType();
        AttributeType at2 = EntryUtils.getBytesAttributeType();

        Value value1 = new Value( at1, "test" );
        Value value2 = new Value( at1, "test" );
        Value value3 = new Value( at1, "TEST" );
        Value value4 = new Value( at1, "tes" );
        Value value5 = new Value( at1, (byte[])null );
        Value valueBytes = new Value( at2, new byte[]
            { 0x01 } );
        Value valueString = new Value( at, "test" );

        assertTrue( value1.equals( value1 ) );
        assertTrue( value1.equals( value2 ) );
        assertTrue( value1.equals( value3 ) );
        assertFalse( value1.equals( value4 ) );
        assertFalse( value1.equals( value5 ) );
        assertTrue( value1.equals( "test" ) );
        assertFalse( value1.equals( null ) );

        assertFalse( value1.equals( valueString ) );
        assertFalse( value1.equals( valueBytes ) );
    }


    /**
     * Test the constructor with bad AttributeType
     */
    @Test
    public void testBadConstructor()
    {
        // create a AT without any syntax
        AttributeType attribute = new EntryUtils.AT( "1.1.3.1" );

        Value value = Value.createValue( attribute );
        
        assertTrue( value.isHumanReadable() );
    }


    /**
     * Tests to make sure the hashCode method is working properly.
     * @throws Exception on errors
     */
    @Test
    public void testHashCode() throws LdapInvalidAttributeValueException
    {
        AttributeType at1 = EntryUtils.getCaseIgnoringAttributeNoNumbersType();
        Value v0 = new Value( at1, "Alex" );
        Value v1 = new Value( at1, "ALEX" );
        Value v2 = new Value( at1, "alex" );

        assertEquals( v0.hashCode(), v1.hashCode() );
        assertEquals( v0.hashCode(), v2.hashCode() );
        assertEquals( v1.hashCode(), v2.hashCode() );

        assertEquals( v0, v1 );
        assertEquals( v0, v2 );
        assertEquals( v1, v2 );

        Value v3 = new Value( at1, "Timber" );

        assertNotSame( v0.hashCode(), v3.hashCode() );

        Value v4 = new Value( at, "Alex" );

        assertNotSame( v0.hashCode(), v4.hashCode() );
    }


    /**
     * Test the compareTo method
     */
    @Test
    public void testCompareTo() throws LdapInvalidAttributeValueException
    {
        AttributeType at1 = EntryUtils.getCaseIgnoringAttributeNoNumbersType();
        Value v0 = new Value( at1, "Alex" );
        Value v1 = new Value( at1, "ALEX" );

        assertEquals( 0, v0.compareTo( v1 ) );
        assertEquals( 0, v1.compareTo( v0 ) );

        Value v2 = new Value( at1, (String)null );

        assertEquals( 1, v0.compareTo( v2 ) );
        assertEquals( -1, v2.compareTo( v0 ) );
    }


    /**
     * Test the clone method
     */
    @Test
    public void testClone() throws LdapException
    {
        AttributeType at1 = EntryUtils.getCaseIgnoringAttributeNoNumbersType();
        Value sv = new Value( at1, "Test" );

        Value sv1 = sv.clone();

        assertEquals( sv, sv1 );

        sv = new Value( "" );

        assertNotSame( sv, sv1 );
        assertEquals( "", sv.getString() );

        sv = new Value( "  This is    a   TEST  " );
        sv1 = sv.clone();

        assertEquals( sv, sv1 );
        assertEquals( sv, sv1 );
    }


    /**
     * Presumes an attribute which constrains it's values to some constant
     * strings: LOW, MEDIUM, HIGH.  Normalization does nothing. MatchingRules
     * are exact case matching.
     *
     * @throws Exception on errors
     */
    @Test
    public void testConstrainedString() throws LdapInvalidAttributeValueException
    {
        s.setSyntaxChecker( new SyntaxChecker( "1.1.1.1" )
        {
            public static final long serialVersionUID = 1L;


            public boolean isValidSyntax( Object value )
            {
                if ( value instanceof String )
                {
                    String strval = ( String ) value;
                    return strval.equals( "HIGH" ) || strval.equals( "LOW" ) || strval.equals( "MEDIUM" );
                }
                return false;
            }
        } );

        mr.setSyntax( s );

        mr.setNormalizer( new NoOpNormalizer( mr.getOid() ) );
        at.setEquality( mr );
        at.setSyntax( s );

        // check that normalization and syntax checks work as expected
        Value value = new Value( at, "HIGH" );
        assertEquals( value.getString(), value.getString() );

        try
        {
            new Value( at, "high" );
            fail();
        }
        catch ( LdapInvalidAttributeValueException liave )
        {
            // expected
        }

        // create a bunch to best tested for equals and in containers
        Value v0 = new Value( at, "LOW" );
        Value v1 = new Value( at, "LOW" );
        Value v2 = new Value( at, "MEDIUM" );
        Value v3 = new Value( at, "HIGH" );

        // check equals
        assertTrue( v0.equals( v1 ) );
        assertTrue( v1.equals( v0 ) );
        assertEquals( 0, v0.compareTo( v1 ) );

        assertFalse( v2.equals( v3 ) );
        assertFalse( v3.equals( v2 ) );
        assertTrue( v2.compareTo( v3 ) > 0 );
        assertTrue( v3.compareTo( v2 ) < 0 );

        // add all except v1 and v5 to a set
        HashSet<Value> set = new HashSet<Value>();
        set.add( v0 );
        set.add( v2 );
        set.add( v3 );

        // check contains method
        assertTrue( set.contains( v1 ), "since v1.equals( v0 ) and v0 was added then this should be true" );

        // check ordering based on the comparator
        List<Value> list = new ArrayList<Value>();
        list.add( v1 );
        list.add( v3 );
        list.add( v0 );
        list.add( v2 );

        Collections.sort( list );

        // High, low, low, medium
        assertTrue( list.get( 0 ).equals( v3 ), "since v0 equals v1 either could be at index 0 & 1" );
        assertTrue( list.get( 1 ).equals( v0 ), "since v0 equals v1 either could be at index 0 & 1" );
        assertTrue( list.get( 2 ).equals( v1 ), "since v2 \"MEDIUM\" should be at index 2" );
        assertTrue( list.get( 3 ).equals( v2 ), "since v3 \"HIGH\" should be at index 3" );

        assertEquals( 4, list.size() );
    }


    /**
     * Creates a string value with an attribute type that is of a syntax
     * which accepts anything.  Also there is no normalization since the
     * value is the same as the normalized value.  This makes the at technically
     * a binary value however it can be dealt with as a string so this test
     * is still OK.
     * @throws Exception on errors
     */
    @Test
    public void testAcceptAllNoNormalization() throws LdapInvalidAttributeValueException
    {
        // check that normalization and syntax checks work as expected
        Value value = new Value( at, "hello" );
        assertEquals( value.getString(), value.getString() );

        // create a bunch to best tested for equals and in containers
        Value v0 = new Value( at, "hello" );
        Value v1 = new Value( at, "hello" );
        Value v2 = new Value( at, "next0" );
        Value v3 = new Value( at, "next1" );
        Value v4 = Value.createValue( at );
        Value v5 = Value.createValue( at );

        // check equals
        assertTrue( v0.equals( v1 ) );
        assertTrue( v1.equals( v0 ) );
        assertTrue( v4.equals( v5 ) );
        assertTrue( v5.equals( v4 ) );
        assertFalse( v2.equals( v3 ) );
        assertFalse( v3.equals( v2 ) );

        // add all except v1 and v5 to a set
        HashSet<Value> set = new HashSet<Value>();
        set.add( v0 );
        set.add( v2 );
        set.add( v3 );
        set.add( v4 );

        // check contains method
        assertTrue( set.contains( v1 ), "since v1.equals( v0 ) and v0 was added then this should be true" );
        assertTrue( set.contains( v5 ), "since v4.equals( v5 ) and v4 was added then this should be true" );

        // check ordering based on the comparator
        ArrayList<Value> list = new ArrayList<Value>();
        list.add( v1 );
        list.add( v3 );
        list.add( v5 );
        list.add( v0 );
        list.add( v2 );
        list.add( v4 );

        Comparator<Value> c = new Comparator<Value>()
        {
            public int compare( Value o1, Value o2 )
            {
                String n1 = null;
                String n2 = null;

                if ( o1 != null )
                {
                    n1 = o1.getString();
                }

                if ( o2 != null )
                {
                    n2 = o2.getString();
                }

                if ( n1 == null )
                {
                    return ( n2 == null ) ? 0 : -1;
                }
                else if ( n2 == null )
                {
                    return 1;
                }

                return mr.getLdapComparator().compare( n1, n2 );
            }
        };

        Collections.sort( list, c );

        assertTrue( list.get( 0 ).equals( v4 ), "since v4 equals v5 and has no value either could be at index 0 & 1" );
        assertTrue( list.get( 0 ).equals( v5 ), "since v4 equals v5 and has no value either could be at index 0 & 1" );
        assertTrue( list.get( 1 ).equals( v4 ), "since v4 equals v5 and has no value either could be at index 0 & 1" );
        assertTrue( list.get( 1 ).equals( v5 ), "since v4 equals v5 and has no value either could be at index 0 & 1" );

        assertTrue( list.get( 2 ).equals( v0 ), "since v0 equals v1 either could be at index 2 & 3" );
        assertTrue( list.get( 2 ).equals( v1 ), "since v0 equals v1 either could be at index 2 & 3" );
        assertTrue( list.get( 3 ).equals( v0 ), "since v0 equals v1 either could be at index 2 & 3" );
        assertTrue( list.get( 3 ).equals( v1 ), "since v0 equals v1 either could be at index 2 & 3" );

        assertTrue( list.get( 4 ).equals( v2 ), "since v2 \"next0\" should be at index 4" );
        assertTrue( list.get( 5 ).equals( v3 ), "since v3 \"next1\" should be at index 5" );

        assertEquals( 6, list.size() );
    }


    /**
     * Test serialization of a Value which has a normalized value
     */
    @Test
    public void testNormalizedStringValueSerialization() throws LdapException, IOException, ClassNotFoundException
    {
        // First check with a value which will be normalized
        Value ssv = new Value( at, "  Test   Test  " );

        assertEquals( 0, ssv.compareTo( " test  test " ) );
        assertEquals( "  Test   Test  ", ssv.getString() );

        Value ssvSer = deserializeValue( serializeValue( ssv ) );

        assertEquals( ssv, ssvSer );
    }


    /**
     * Test serialization of a Value which does not have a normalized value
     */
    @Test
    public void testNoNormalizedStringValueSerialization() throws LdapException, IOException, ClassNotFoundException
    {
        // First check with a value which will be normalized
        Value ssv = new Value( at, "test" );

        assertEquals( 0, ssv.compareTo( " test " ) );
        assertEquals( "test", ssv.getString() );

        Value ssvSer = deserializeValue( serializeValue( ssv ) );

        assertEquals( ssv, ssvSer );
    }


    /**
     * Test serialization of a null Value
     */
    @Test
    public void testNullStringValueSerialization() throws LdapException, IOException, ClassNotFoundException
    {
        // First check with a value which will be normalized
        Value ssv = Value.createValue( at );

        assertEquals( 0, ssv.compareTo( ( String ) null ) );
        assertNull( ssv.getString() );

        Value ssvSer = deserializeValue( serializeValue( ssv ) );

        assertEquals( ssv, ssvSer );
    }


    /**
     * Test serialization of an empty Value
     */
    @Test
    public void testEmptyStringValueSerialization() throws LdapException, IOException, ClassNotFoundException
    {
        // First check with a value which will be normalized
        Value ssv = new Value( at, "" );

        assertEquals( 0, ssv.compareTo( "  " ) );
        assertEquals( "", ssv.getString() );

        Value ssvSer = deserializeValue( serializeValue( ssv ) );

        assertEquals( ssv, ssvSer );
    }


    /**
     * Test serialization of an empty Value
     */
    @Test
    public void testStringValueEmptyNormalizedSerialization() throws LdapException, IOException, ClassNotFoundException
    {
        // First check with a value which will be normalized
        Value ssv = new Value( "  " );

        assertEquals( "  ", ssv.getString() );

        Value ssvSer = deserializeValue( serializeValue( ssv ) );

        assertEquals( ssv, ssvSer );
    }
}
