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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.apache.bcel.generic.ClassElementValueGen;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.ElementValueGen;
import org.apache.bcel.generic.EnumElementValueGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.SimpleElementValueGen;
import org.junit.jupiter.api.Test;

class ElementValueGenTest extends AbstractTest {
    private void checkSerialize(final ElementValueGen evgBefore, final ConstantPoolGen cpg) throws IOException {
        final String beforeValue = evgBefore.stringifyValue();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (DataOutputStream dos = new DataOutputStream(baos)) {
            evgBefore.dump(dos);
            dos.flush();
        }
        final ElementValueGen evgAfter;
        try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
            evgAfter = ElementValueGen.readElementValue(dis, cpg);
        }
        final String afterValue = evgAfter.stringifyValue();
        assertEquals(beforeValue, afterValue, "Deserialization failed");
    }

    private ClassGen createClassGen(final String className) {
        return new ClassGen(className, "java.lang.Object", "<generated>", Const.ACC_PUBLIC | Const.ACC_SUPER, null);
    }

    @Test
    void testCreateBooleanElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_BOOLEAN, cp, true);
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupInteger(1); // 1 == true
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateByteElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_BYTE, cp, (byte) 'z');
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupInteger((byte) 'z');
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateCharElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_CHAR, cp, 't');
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupInteger('t');
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    // //
    // Create class element value
    @Test
    void testCreateClassElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final ObjectType classType = new ObjectType("java.lang.Integer");
        final ClassElementValueGen evg = new ClassElementValueGen(classType, cp);
        assertTrue(evg.getClassString().contains("Integer"), "Unexpected value for contained class: '" + evg.getClassString() + "'");
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateDoubleElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_DOUBLE, cp, 333.44);
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupDouble(333.44);
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    // //
    // Create enum element value
    @Test
    void testCreateEnumElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final ObjectType enumType = new ObjectType("SimpleEnum"); // Supports rainbow
        // :)
        final EnumElementValueGen evg = new EnumElementValueGen(enumType, "Red", cp);
        // Creation of an element like that should leave a new entry in the
        // cpool
        assertEquals(cp.lookupUtf8("Red"), evg.getValueIndex(), "The new ElementValue value index should match the contents of the constantpool");
        // BCELBUG: Should the class signature or class name be in the constant
        // pool? (see note in ConstantPool)
        // assertTrue("The new ElementValue type index should match the contents
        // of the constantpool but "+
        // evg.getTypeIndex()+"!="+cp.lookupClass(enumType.getSignature()),
        // evg.getTypeIndex()==cp.lookupClass(enumType.getSignature()));
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateFloatElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_FLOAT, cp, 111.222f);
        // Creation of an element like that should leave a new entry in the
        // cpool
        assertEquals(cp.lookupFloat(111.222f), evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    /**
     * Create primitive element values
     */
    @Test
    void testCreateIntegerElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_INT, cp, 555);
        // Creation of an element like that should leave a new entry in the
        // cpool
        assertEquals(cp.lookupInteger(555), evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateLongElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_LONG, cp, 3334455L);
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupLong(3334455L);
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    @Test
    void testCreateShortElementValue() throws Exception {
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_SHORT, cp, (short) 42);
        // Creation of an element like that should leave a new entry in the
        // cpool
        final int idx = cp.lookupInteger(42);
        assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }

    // //
    // Create string element values
    @Test
    void testCreateStringElementValue() throws Exception {
        // Create HelloWorld
        final ClassGen cg = createClassGen("HelloWorld");
        final ConstantPoolGen cp = cg.getConstantPool();
        final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.STRING, cp, "hello");
        // Creation of an element like that should leave a new entry in the
        // cpool
        assertEquals(cp.lookupUtf8("hello"), evg.getIndex(), "Should have the same index in the constantpool");
        checkSerialize(evg, cp);
    }
}
