/*
 * Copyright (c) 1998, 2021 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.sessions;

import java.io.StringWriter;
import java.util.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * PERF: Optimized record implementation using arrays instead of Vector.
 * Currently only used when fetch rows from the database.
 */
public class ArrayRecord extends DatabaseRecord {
    protected DatabaseField[] fieldsArray;
    protected Object[] valuesArray;

    protected ArrayRecord() {
        super();
    }

    public ArrayRecord(Vector fields, DatabaseField[] fieldsArray, Object[] valuesArray) {
        super(fields, null, fieldsArray.length);
        this.fieldsArray = fieldsArray;
        this.valuesArray = valuesArray;
    }

    /**
     * Reset the fields and values from the arrays.
     * This removes the optimization if a non-optimized method is called.
     */
    protected void checkValues() {
        if (this.values == null) {
            this.values = new NonSynchronizedVector(this.valuesArray.length);
            for (Object value : this.valuesArray) {
                this.values.add(value);
            }
        }
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.  Will not check,
     * will simply add to the end of the row
     */
    @Override
    public void add(DatabaseField key, Object value) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.add(key, value);
    }

    /**
     * PUBLIC:
     * Clear the contents of the row.
     */
    @Override
    public void clear() {
        this.fieldsArray = null;
        this.valuesArray = null;
        super.clear();
    }

    /**
     * INTERNAL:
     * Clone the row and its values.
     */
    @Override
    public AbstractRecord clone() {
        checkValues();
        return super.clone();
    }

    /**
     * INTERNAL:
     * Check if the field is contained in the row.
     */
    @Override
    public boolean containsKey(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return true;
                }
            }
            for (DatabaseField field : this.fieldsArray) {
                if ((field == key) || field.equals(key)) {
                    return true;
                }
            }
            return false;
        } else {
            return super.containsKey(key);
        }
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the row.
     */
    @Override
    public boolean containsValue(Object value) {
        if (this.valuesArray != null) {
            for (Object rowValue : this.valuesArray) {
                if ((value == rowValue) || rowValue.equals(value)) {
                    return true;
                }
            }
            return false;
        } else {
            return super.containsValue(value);
        }
    }

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing null is returned.
     */
    @Override
    public Object get(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return this.valuesArray[index];
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    return this.valuesArray[fieldIndex];
                }
            }
            return null;
        } else {
            return super.get(key);
        }
    }

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing DatabaseRow.noEntry is returned.
     */
    @Override
    public Object getIndicatingNoEntry(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return this.valuesArray[index];
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    return this.valuesArray[fieldIndex];
                }
            }
            return AbstractRecord.noEntry;
        } else {
            return super.get(key);
        }
    }

    /**
     * INTERNAL:
     * Returns the row's field with the same name.
     */
    @Override
    public DatabaseField getField(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return field;
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    return field;
                }
            }
            return null;
        } else {
            return super.getField(key);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public Vector getFields() {
        checkValues();
        return super.getFields();
    }

    /**
     * INTERNAL:
     */
    @Override
    public Vector getValues() {
        checkValues();
        return super.getValues();
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.
     */
    @Override
    public Object put(DatabaseField key, Object value) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        return super.put(key, value);
    }

    /**
     * INTERNAL:
     * Remove the field key from the row.
     */
    @Override
    public Object remove(DatabaseField key) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        return super.remove(key);
    }

    /**
     * INTERNAL:
     * replaces the value at index with value
     */
    @Override
    public void replaceAt(Object value, int index) {
        if (this.valuesArray != null) {
            this.valuesArray[index] = value;
        } else {
            super.replaceAt(value, index);
        }
    }

    /**
     * INTERNAL:
     * replaces the value at field with value
     */
    @Override
    public void replaceAt(Object value, DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    this.valuesArray[index] = value;
                    return;
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    this.valuesArray[fieldIndex] = value;
                    return;
                }
            }
        } else {
            super.replaceAt(value, key);
        }
    }

    @Override
    protected void setFields(Vector fields) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.setFields(fields);
    }

    @Override
    protected void setValues(Vector values) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.setValues(values);
    }

    /**
     * PUBLIC:
     * Return the number of field/value pairs in the row.
     */
    @Override
    public int size() {
        if (this.fieldsArray == null) {
            return this.fields.size();
        } else {
            return this.fieldsArray.length;
        }
    }

    @Override
    public String toString() {
        if (this.valuesArray != null) {
            StringWriter writer = new StringWriter();
            writer.write(Helper.getShortClassName(getClass()));
            writer.write("(");
            writer.write(toStringAditional());
            for (int index = 0; index < this.fieldsArray.length; index++) {
                writer.write(Helper.cr());
                writer.write("\t");
                writer.write(String.valueOf(this.fieldsArray[index]));
                writer.write(" => ");
                writer.write(String.valueOf(this.valuesArray[index]));
            }
            if (this.sopObject != null) {
                writer.write(Helper.cr());
                writer.write(" sopObject = ");
                writer.write(this.sopObject.toString());
            }
            writer.write(")");

            return writer.toString();
        } else {
            return super.toString();
        }
    }

    protected String toStringAditional() {
        return "";
    }
}
