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

import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Arrays;

/**
 * An implementation of SparseArray specialized for {@link android.graphics.RectF}.
 * <p>
 * As this is a sparse array, it represents an array of {@link RectF} most of which are null. This
 * class could be in some other packages like android.graphics or android.util but currently
 * belong to android.view.inputmethod because this class is hidden and used only in input method
 * framework.
 * </p>
 * @hide
 */
public final class SparseRectFArray implements Parcelable {
    /**
     * The keys, in ascending order, of those {@link RectF} that are not null. For example,
     * {@code [null, null, null, Rect1, null, Rect2]} would be represented by {@code [3,5]}.
     * @see #mCoordinates
     */
    private final int[] mKeys;

    /**
     * Stores coordinates of the rectangles, in the order of
     * {@code rects[mKeys[0]].left}, {@code rects[mKeys[0]].top},
     * {@code rects[mKeys[0]].right}, {@code rects[mKeys[0]].bottom},
     * {@code rects[mKeys[1]].left}, {@code rects[mKeys[1]].top},
     * {@code rects[mKeys[1]].right}, {@code rects[mKeys[1]].bottom},
     * {@code rects[mKeys[2]].left}, {@code rects[mKeys[2]].top}, ....
     */
    private final float[] mCoordinates;

    /**
     * Stores visibility information.
     */
    private final int[] mFlagsArray;

    public SparseRectFArray(final Parcel source) {
        mKeys = source.createIntArray();
        mCoordinates = source.createFloatArray();
        mFlagsArray = source.createIntArray();
    }

    /**
     * Used to package this object into a {@link Parcel}.
     *
     * @param dest The {@link Parcel} to be written.
     * @param flags The flags used for parceling.
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeIntArray(mKeys);
        dest.writeFloatArray(mCoordinates);
        dest.writeIntArray(mFlagsArray);
    }

    @Override
    public int hashCode() {
        // TODO: Improve the hash function.
        if (mKeys == null || mKeys.length == 0) {
            return 0;
        }
        int hash = mKeys.length;
        // For performance reasons, only the first rectangle is used for the hash code now.
        for (int i = 0; i < 4; i++) {
            hash *= 31;
            hash += mCoordinates[i];
        }
        hash *= 31;
        hash += mFlagsArray[0];
        return hash;
    }

    @Override
    public boolean equals(Object obj){
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof SparseRectFArray)) {
            return false;
        }
        final SparseRectFArray that = (SparseRectFArray) obj;

        return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates)
                && Arrays.equals(mFlagsArray, that.mFlagsArray);
    }

    @Override
    public String toString() {
        if (mKeys == null || mCoordinates == null || mFlagsArray == null) {
            return "SparseRectFArray{}";
        }
        final StringBuilder sb = new StringBuilder();
        sb.append("SparseRectFArray{");
        for (int i = 0; i < mKeys.length; i++) {
            if (i != 0) {
                sb.append(", ");
            }
            final int baseIndex = i * 4;
            sb.append(mKeys[i]);
            sb.append(":[");
            sb.append(mCoordinates[baseIndex + 0]);
            sb.append(",");
            sb.append(mCoordinates[baseIndex + 1]);
            sb.append("],[");
            sb.append(mCoordinates[baseIndex + 2]);
            sb.append(",");
            sb.append(mCoordinates[baseIndex + 3]);
            sb.append("]:flagsArray=");
            sb.append(mFlagsArray[i]);
        }
        sb.append("}");
        return sb.toString();
    }

    /**
     * Builder for {@link SparseRectFArray}. This class is not designed to be thread-safe.
     * @hide
     */
    public static final class SparseRectFArrayBuilder {
        /**
         * Throws {@link IllegalArgumentException} to make sure that this class is correctly used.
         * @param key key to be checked.
         */
        private void checkIndex(final int key) {
            if (mCount == 0) {
                return;
            }
            if (mKeys[mCount - 1] >= key) {
                throw new IllegalArgumentException("key must be greater than all existing keys.");
            }
        }

        /**
         * Extends the internal array if necessary.
         */
        private void ensureBufferSize() {
            if (mKeys == null) {
                mKeys = new int[INITIAL_SIZE];
            }
            if (mCoordinates == null) {
                mCoordinates = new float[INITIAL_SIZE * 4];
            }
            if (mFlagsArray == null) {
                mFlagsArray = new int[INITIAL_SIZE];
            }
            final int requiredIndexArraySize = mCount + 1;
            if (mKeys.length <= requiredIndexArraySize) {
                final int[] newArray = new int[requiredIndexArraySize * 2];
                System.arraycopy(mKeys, 0, newArray, 0, mCount);
                mKeys = newArray;
            }
            final int requiredCoordinatesArraySize = (mCount + 1) * 4;
            if (mCoordinates.length <= requiredCoordinatesArraySize) {
                final float[] newArray = new float[requiredCoordinatesArraySize * 2];
                System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4);
                mCoordinates = newArray;
            }
            final int requiredFlagsArraySize = requiredIndexArraySize;
            if (mFlagsArray.length <= requiredFlagsArraySize) {
                final int[] newArray = new int[requiredFlagsArraySize * 2];
                System.arraycopy(mFlagsArray, 0, newArray, 0, mCount);
                mFlagsArray = newArray;
            }
        }

        /**
         * Puts the rectangle with an integer key.
         * @param key the key to be associated with the rectangle. It must be greater than all
         * existing keys that have been previously specified.
         * @param left left of the rectangle.
         * @param top top of the rectangle.
         * @param right right of the rectangle.
         * @param bottom bottom of the rectangle.
         * @param flags an arbitrary integer value to be associated with this rectangle.
         * @return the receiver object itself for chaining method calls.
         * @throws IllegalArgumentException If the index is not greater than all of existing keys.
         */
        public SparseRectFArrayBuilder append(final int key,
                final float left, final float top, final float right, final float bottom,
                final int flags) {
            checkIndex(key);
            ensureBufferSize();
            final int baseCoordinatesIndex = mCount * 4;
            mCoordinates[baseCoordinatesIndex + 0] = left;
            mCoordinates[baseCoordinatesIndex + 1] = top;
            mCoordinates[baseCoordinatesIndex + 2] = right;
            mCoordinates[baseCoordinatesIndex + 3] = bottom;
            final int flagsIndex = mCount;
            mFlagsArray[flagsIndex] = flags;
            mKeys[mCount] = key;
            ++mCount;
            return this;
        }
        private int mCount = 0;
        private int[] mKeys = null;
        private float[] mCoordinates = null;
        private int[] mFlagsArray = null;
        private static int INITIAL_SIZE = 16;

        public boolean isEmpty() {
            return mCount <= 0;
        }

        /**
         * @return {@link SparseRectFArray} using parameters in this {@link SparseRectFArray}.
         */
        public SparseRectFArray build() {
            return new SparseRectFArray(this);
        }

        public void reset() {
            if (mCount == 0) {
                mKeys = null;
                mCoordinates = null;
                mFlagsArray = null;
            }
            mCount = 0;
        }
    }

    private SparseRectFArray(final SparseRectFArrayBuilder builder) {
        if (builder.mCount == 0) {
            mKeys = null;
            mCoordinates = null;
            mFlagsArray = null;
        } else {
            mKeys = new int[builder.mCount];
            mCoordinates = new float[builder.mCount * 4];
            mFlagsArray = new int[builder.mCount];
            System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount);
            System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4);
            System.arraycopy(builder.mFlagsArray, 0, mFlagsArray, 0, builder.mCount);
        }
    }

    public RectF get(final int index) {
        if (mKeys == null) {
            return null;
        }
        if (index < 0) {
            return null;
        }
        final int arrayIndex = Arrays.binarySearch(mKeys, index);
        if (arrayIndex < 0) {
            return null;
        }
        final int baseCoordIndex = arrayIndex * 4;
        return new RectF(mCoordinates[baseCoordIndex],
                mCoordinates[baseCoordIndex + 1],
                mCoordinates[baseCoordIndex + 2],
                mCoordinates[baseCoordIndex + 3]);
    }

    public int getFlags(final int index, final int valueIfKeyNotFound) {
        if (mKeys == null) {
            return valueIfKeyNotFound;
        }
        if (index < 0) {
            return valueIfKeyNotFound;
        }
        final int arrayIndex = Arrays.binarySearch(mKeys, index);
        if (arrayIndex < 0) {
            return valueIfKeyNotFound;
        }
        return mFlagsArray[arrayIndex];
    }

    /**
     * Used to make this class parcelable.
     */
    public static final Parcelable.Creator<SparseRectFArray> CREATOR =
            new Parcelable.Creator<SparseRectFArray>() {
                @Override
                public SparseRectFArray createFromParcel(Parcel source) {
                    return new SparseRectFArray(source);
                }
                @Override
                public SparseRectFArray[] newArray(int size) {
                    return new SparseRectFArray[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }
}

