/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Denise Smith  July 05, 2009 - Initial implementation
package org.eclipse.persistence.testing.jaxb.annotations;

import java.util.List;

import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.adapters.HexBinaryAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class TestObject {
    @XmlElement(type = String.class)
    @XmlJavaTypeAdapter(HexBinaryAdapter.class)
    protected List<byte[]> byteArrayListTest;

    @XmlElement(type = String.class)
    @XmlJavaTypeAdapter(HexBinaryAdapter.class)
    protected byte[] byteArrayTest;

    @XmlElement(type = Boolean.class)
    protected Object booleanTest;

    @XmlElement(type = Boolean.class)
    protected List<Object> booleanListTest;

    @XmlElement (defaultValue="1")
    public int fld1;

    public boolean equals(Object compareobject){
        if(!(compareobject instanceof TestObject)){
            return false;
        }
        if(fld1 != ((TestObject)compareobject).fld1){
            return false;
        }

        if(!booleanTest.equals(((TestObject)compareobject).booleanTest)){
            return false;
        }
        if(booleanListTest.size() != ((TestObject)compareobject).booleanListTest.size()){
            return false;
        }

        for(int i=0;i<booleanListTest.size(); i++){
            if(!booleanListTest.get(i).equals(((TestObject)compareobject).booleanListTest.get(i))){
                return false;
            }
        }

        if(!equalByteArrays(byteArrayTest, ((TestObject)compareobject).byteArrayTest)){
            return false;
        }
        if(byteArrayListTest.size() != ((TestObject)compareobject).byteArrayListTest.size()){
            return false;
        }
        for(int i=0;i< byteArrayListTest.size(); i++){
            Object next = byteArrayListTest.get(i);
            Object nextCompare = ((TestObject)compareobject).byteArrayListTest.get(i);
            if(!equalByteArrays(next, nextCompare)){
                return false;
            }
        }

        return true;
    }

    private boolean equalByteArrays(Object obj1, Object obj2) {
        if(obj1 instanceof byte[] && obj2 instanceof byte[]){
            byte[] array1 = (byte[])obj1;
            byte[] array2 = (byte[])obj2;
            //covers the case where both are null
            if(array1 == array2) {
                return true;
            }
            if (array1.length != array2.length) {
                return false;
            }

            // check each base64 byte in sequence
            for (int i = 0; i < array1.length; i++) {
                if (array1[i] != array2[i]) {
                    return false;
                }
            }

            return true;
        }
        return false;
    }
}
