/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed 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 android.hardware.camera2.params;

import static android.hardware.camera2.params.RggbChannelVector.BLUE;
import static android.hardware.camera2.params.RggbChannelVector.COUNT;
import static android.hardware.camera2.params.RggbChannelVector.GREEN_EVEN;
import static android.hardware.camera2.params.RggbChannelVector.GREEN_ODD;
import static android.hardware.camera2.params.RggbChannelVector.RED;

import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
import static com.android.internal.util.Preconditions.checkArgumentPositive;
import static com.android.internal.util.Preconditions.checkArrayElementsInRange;
import static com.android.internal.util.Preconditions.checkNotNull;

import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.utils.HashCodeHelpers;

import java.util.Arrays;

/**
 * Immutable class for describing a {@code 4 x N x M} lens shading map of floats.
 *
 * @see CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP
 */
public final class LensShadingMap {

    /**
     * The smallest gain factor in this map.
     *
     * <p>All values in this map will be at least this large.</p>
     */
    public static final float MINIMUM_GAIN_FACTOR = 1.0f;

    /**
     * Create a new immutable LensShadingMap instance.
     *
     * <p>The elements must be stored in a row-major order (fully packed).</p>
     *
     * <p>This constructor takes over the array; do not write to the array afterwards.</p>
     *
     * @param elements
     *          An array of elements whose length is
     *          {@code RggbChannelVector.COUNT * rows * columns}
     *
     * @throws IllegalArgumentException
     *            if the {@code elements} array length is invalid,
     *            if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR},
     *            or if rows or columns is not positive
     * @throws NullPointerException
     *            if {@code elements} is {@code null}
     *
     * @hide
     */
    public LensShadingMap(final float[] elements, final int rows, final int columns) {

        mRows = checkArgumentPositive(rows, "rows must be positive");
        mColumns = checkArgumentPositive(columns, "columns must be positive");
        mElements = checkNotNull(elements, "elements must not be null");

        if (elements.length != getGainFactorCount()) {
            throw new IllegalArgumentException("elements must be " + getGainFactorCount() +
                    " length, received " + elements.length);
        }

        // Every element must be finite and >= 1.0f
        checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements");
    }

    /**
     * Get the number of rows in this map.
     */
    public int getRowCount() {
        return mRows;
    }

    /**
     * Get the number of columns in this map.
     */
    public int getColumnCount() {
        return mColumns;
    }

    /**
     * Get the total number of gain factors in this map.
     *
     * <p>A single gain factor contains exactly one color channel.
     * Use with {@link #copyGainFactors} to allocate a large-enough array.</p>
     */
    public int getGainFactorCount() {
        return mRows * mColumns * COUNT;
    }

    /**
     * Get a single color channel gain factor from this lens shading map by its row and column.
     *
     * <p>The rows must be within the range [0, {@link #getRowCount}),
     * the column must be within the range [0, {@link #getColumnCount}),
     * and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p>
     *
     * <p>The channel order is {@code [R, Geven, Godd, B]}, where
     * {@code Geven} is the green channel for the even rows of a Bayer pattern, and
     * {@code Godd} is the odd rows.
     * </p>
     *
     * @param colorChannel color channel from {@code [R, Geven, Godd, B]}
     * @param column within the range [0, {@link #getColumnCount})
     * @param row within the range [0, {@link #getRowCount})
     *
     * @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR}
     *
     * @throws IllegalArgumentException if any of the parameters was out of range
     *
     * @see RggbChannelVector#RED
     * @see RggbChannelVector#GREEN_EVEN
     * @see RggbChannelVector#GREEN_ODD
     * @see RggbChannelVector#BLUE
     * @see #getRowCount
     * @see #getColumnCount
     */
    public float getGainFactor(final int colorChannel, final int column, final int row) {
        if (colorChannel < 0 || colorChannel > COUNT) {
            throw new IllegalArgumentException("colorChannel out of range");
        } else if (column < 0 || column >= mColumns) {
            throw new IllegalArgumentException("column out of range");
        } else if (row < 0 || row >= mRows) {
            throw new IllegalArgumentException("row out of range");
        }

        return mElements[colorChannel + (row * mColumns +  column) * COUNT ];
    }

    /**
     * Get a gain factor vector from this lens shading map by its row and column.
     *
     * <p>The rows must be within the range [0, {@link #getRowCount}),
     * the column must be within the range [0, {@link #getColumnCount}).</p>
     *
     * @param column within the range [0, {@link #getColumnCount})
     * @param row within the range [0, {@link #getRowCount})
     *
     * @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR}
     *
     * @throws IllegalArgumentException if any of the parameters was out of range
     *
     * @see #getRowCount
     * @see #getColumnCount
     */
    public RggbChannelVector getGainFactorVector(final int column, final int row) {
        if (column < 0 || column >= mColumns) {
            throw new IllegalArgumentException("column out of range");
        } else if (row < 0 || row >= mRows) {
            throw new IllegalArgumentException("row out of range");
        }

        final int offset = (row * mColumns +  column) * COUNT;

        final float red =
                mElements[RED + offset];
        final float greenEven =
                mElements[GREEN_EVEN + offset];
        final float greenOdd =
                mElements[GREEN_ODD + offset];
        final float blue =
                mElements[BLUE + offset];

        return new RggbChannelVector(red, greenEven, greenOdd, blue);
    }

    /**
     * Copy all gain factors in row-major order from this lens shading map into the destination.
     *
     * <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p>
     *
     * @param destination
     *          an array big enough to hold at least {@link RggbChannelVector#COUNT}
     *          elements after the {@code offset}
     * @param offset
     *          a non-negative offset into the array
     * @throws NullPointerException
     *          If {@code destination} was {@code null}
     * @throws IllegalArgumentException
     *          If offset was negative
     * @throws ArrayIndexOutOfBoundsException
     *          If there's not enough room to write the elements at the specified destination and
     *          offset.
     *
     * @see CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP
     */
    public void copyGainFactors(final float[] destination, final int offset) {
        checkArgumentNonnegative(offset, "offset must not be negative");
        checkNotNull(destination, "destination must not be null");
        if (destination.length + offset < getGainFactorCount()) {
            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
        }

        System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount());
    }

    /**
     * Check if this LensShadingMap is equal to another LensShadingMap.
     *
     * <p>Two lens shading maps are equal if and only if they have the same rows/columns,
     * and all of their elements are {@link Object#equals equal}.</p>
     *
     * @return {@code true} if the objects were equal, {@code false} otherwise
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (obj instanceof LensShadingMap) {
            final LensShadingMap other = (LensShadingMap) obj;
            return mRows == other.mRows
                    && mColumns == other.mColumns
                    && Arrays.equals(mElements, other.mElements);
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        int elemsHash = HashCodeHelpers.hashCode(mElements);
        return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash);
    }

    /**
     * Return the LensShadingMap as a string representation.
     *
     * <p> {@code "LensShadingMap{R:([%f, %f, ... %f], ... [%f, %f, ... %f]), G_even:([%f, %f, ...
     *  %f], ... [%f, %f, ... %f]), G_odd:([%f, %f, ... %f], ... [%f, %f, ... %f]), B:([%f, %f, ...
     *  %f], ... [%f, %f, ... %f])}"},
     * where each {@code %f} represents one gain factor and each {@code [%f, %f, ... %f]} represents
     * a row of the lens shading map</p>
     *
     * @return string representation of {@link LensShadingMap}
     */
    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        str.append("LensShadingMap{");

        final String channelPrefix[] = {"R:(", "G_even:(", "G_odd:(", "B:("};

        for (int ch = 0; ch < COUNT; ch++) {
            str.append(channelPrefix[ch]);

            for (int r = 0; r < mRows; r++) {
                str.append("[");
                for (int c = 0; c < mColumns; c++) {
                    float gain = getGainFactor(ch, c, r);
                    str.append(gain);
                    if (c < mColumns - 1) {
                        str.append(", ");
                    }
                }
                str.append("]");
                if (r < mRows - 1) {
                    str.append(", ");
                }
            }

            str.append(")");
            if (ch < COUNT - 1) {
                str.append(", ");
            }
        }

        str.append("}");
        return str.toString();
    }

    private final int mRows;
    private final int mColumns;
    private final float[] mElements;
}
