/*
 * 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.nifi.serialization.record;

import org.apache.nifi.serialization.record.util.IllegalTypeConversionException;

import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

public interface Record {

    RecordSchema getSchema();

    /**
     * Indicates whether or not field values for this record are expected to be coerced into the type designated by the schema.
     * If <code>true</code>, then it is safe to assume that calling {@link #getValue(RecordField)} will return an Object of the appropriate
     * type according to the schema, or an object that can be coerced into the appropriate type. If type checking
     * is not enabled, then calling {@link #getValue(RecordField)} can return an object of any type.
     *
     * @return <code>true</code> if type checking is enabled, <code>false</code> otherwise.
     */
    boolean isTypeChecked();

    /**
     * If <code>true</code>, any field that is added to the record will be drop unless the field is known by the schema
     *
     * @return <code>true</code> if fields that are unknown to the schema will be dropped, <code>false</code>
     *         if all field values are retained.
     */
    boolean isDropUnknownFields();

    /**
     * Updates the Record's schema to to incorporate all of the fields in the given schema. If both schemas have a
     * field with the same name but a different type, then the existing schema will be updated to have a
     * {@link RecordFieldType#CHOICE} field with both types as choices. If two fields have the same name but different
     * default values, then the default value that is already in place will remain the default value, unless the current
     * default value is <code>null</code>. Note that all values for this Record will still be valid according
     * to this Record's Schema after this operation completes, as no type will be changed except to become more
     * lenient. However, if incorporating the other schema does modify this schema, then the schema text
     * returned by {@link RecordSchema#getSchemaText() getSchemaText()}, the schema format returned by {@link RecordSchema#getSchemaFormat() getSchemaFormat()}, and
     * the SchemaIdentifier returned by {@link RecordSchema#getIdentifier() getIdentifier()} for this record's schema may all become Empty.
     *
     * @param other the other schema to incorporate into this Record's schema
     *
     * @throws UnsupportedOperationException if this record does not support incorporating other schemas
     */
    void incorporateSchema(RecordSchema other);

    /**
     * Updates the Record's schema to incorporate all of the fields that were added via the {@link #setValue(RecordField, Object)}
     * method that did not exist in the schema.
     *
     * @throws UnsupportedOperationException if this record does not support incorporating other fields
     */
    void incorporateInactiveFields();

    /**
     * <p>
     * Returns a view of the the values of the fields in this Record. Note that this method returns values only for
     * those entries in the Record's schema. This allows the Record to guarantee that it will return the values in
     * the order dictated by the schema.
     * </p>
     *
     * <b>NOTE:</b> The array that is returned may be an underlying array that is backing
     * the contents of the Record. As such, modifying the array in any way may result in
     * modifying the record.
     *
     * @return a view of the values of the fields in this Record
     */
    Object[] getValues();

    Object getValue(String fieldName);

    Object getValue(RecordField field);

    String getAsString(String fieldName);

    String getAsString(String fieldName, String format);

    String getAsString(RecordField field, String format);

    Long getAsLong(String fieldName);

    Integer getAsInt(String fieldName);

    Double getAsDouble(String fieldName);

    Float getAsFloat(String fieldName);

    Record getAsRecord(String fieldName, RecordSchema schema);

    Boolean getAsBoolean(String fieldName);

    Date getAsDate(String fieldName, String format);

    Object[] getAsArray(String fieldName);

    Optional<SerializedForm> getSerializedForm();

    /**
     * Updates the value of the field with the given name to the given value. If the field specified
     * is not present in this Record's schema, this method will do nothing. If this method does change
     * any value in the Record, any {@link SerializedForm} that was provided will be removed (i.e., any
     * subsequent call to {@link #getSerializedForm()} will return an empty Optional).
     *
     * @param fieldName the name of the field to update
     * @param value the new value to set
     *
     * @throws IllegalTypeConversionException if the value is not of the correct type, as defined
     *             by the schema, and cannot be coerced into the correct type.
     */
    void setValue(String fieldName, Object value);

    /**
     * Updates the value of the given field to the given value. If the field specified is not present in this Record's schema,
     * this method will track of the field as an 'inactive field', which can then be added into the Record's schema via the
     * {@link #incorporateInactiveFields} method. This method should not be called after each invocation of {@link #setValue(RecordField, Object)}
     * but rather should be called only once all updates to the Record have completed, in order to optimize performance.
     *
     * If this method changes any value in the Record, any {@link SerializedForm} that was provided will be removed (i.e., any
     * subsequent call to {@link #getSerializedForm()}} will return an empty Optional).
     *
     * @param field the field to update
     * @param value the value to set
     */
    void setValue(RecordField field, Object value);

    /**
     * Updates the value of a the specified index of a field. If the field specified
     * is not present in this Record's schema, this method will do nothing. If the field specified
     * is not an Array, an IllegalArgumentException will be thrown. If the field specified is an array
     * but the array has fewer elements than the specified index, this method will do nothing. If this method does change
     * any value in the Record, any {@link SerializedForm} that was provided will be removed (i.e., any
     * subsequent call to {@link #getSerializedForm()} will return an empty Optional).
     *
     * @param fieldName the name of the field to update
     * @param arrayIndex the 0-based index into the array that should be updated. If this value is larger than the
     *            number of elements in the array, or if the array is null, this method will do nothing.
     * @param value the new value to set
     *
     * @throws IllegalTypeConversionException if the value is not of the correct type, as defined
     *             by the schema, and cannot be coerced into the correct type; or if the field with the given
     *             name is not an Array
     * @throws IllegalArgumentException if the arrayIndex is less than 0.
     */
    void setArrayValue(String fieldName, int arrayIndex, Object value);

    /**
     * Updates the value of a the specified key in a Map field. If the field specified
     * is not present in this Record's schema, this method will do nothing. If the field specified
     * is not a Map field, an IllegalArgumentException will be thrown. If this method does change
     * any value in the Record, any {@link SerializedForm} that was provided will be removed (i.e., any
     * subsequent call to {@link #getSerializedForm()} will return an empty Optional).
     *
     * @param fieldName the name of the field to update
     * @param mapKey the key in the map of the entry to update
     * @param value the new value to set
     *
     * @throws IllegalTypeConversionException if the value is not of the correct type, as defined
     *             by the schema, and cannot be coerced into the correct type; or if the field with the given
     *             name is not a Map
     */
    void setMapValue(String fieldName, String mapKey, Object value);

    /**
     * Returns a Set that contains the names of all of the fields that are present in the Record, regardless of
     * whether or not those fields are contained in the schema. To determine which fields exist in the Schema, use
     * {@link #getSchema()}.{@link RecordSchema#getFieldNames() getFieldNames()} instead.
     *
     * @return a Set that contains the names of all of the fields that are present in the Record
     */
    Set<String> getRawFieldNames();

    /**
     * Converts the Record into a Map whose keys are the same as the Record's field names and the values are the field values
     * @return a Map that represents the values in the Record.
     */
    Map<String, Object> toMap();
}
