/*
 * 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.phoenix.schema.tuple;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.phoenix.query.QueryConstants.ENCODED_CQ_COUNTER_INITIAL_VALUE;
import static org.apache.phoenix.query.QueryConstants.ENCODED_EMPTY_COLUMN_NAME;

import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

import javax.annotation.concurrent.NotThreadSafe;

import org.apache.hadoop.hbase.Cell;
import org.apache.phoenix.schema.PTable.ImmutableStorageScheme;
import org.apache.phoenix.schema.PTable.QualifierEncodingScheme;

/**
 * List implementation that provides indexed based look up when the cell column qualifiers are positive numbers. 
 * These qualifiers are generated by using one of the column qualifier encoding schemes specified in {@link ImmutableStorageScheme}. 
 * The api methods in this list assume that the caller wants to see
 * and add only non null elements in the list. 
 * <p>
 * Please note that this implementation doesn't implement all the optional methods of the 
 * {@link List} interface. Such unsupported methods could violate the basic invariance of the list that every cell with
 * an encoded column qualifier has a fixed position in the list.
 * </p>
 * <p>
 * An important performance characteristic of this list is that doing look up on the basis of index via {@link #get(int)}
 * is an O(n) operation. This makes iterating through the list using {@link #get(int)} an O(n^2) operation.
 * Instead, for iterating through the list, one should use the iterators created through {@link #iterator()} or 
 * {@link #listIterator()}. Do note that getting an element using {@link #getCellForColumnQualifier(int)} is an O(1) operation
 * and should generally be the way for accessing elements in the list.
 * </p> 
 */
@NotThreadSafe
public class EncodedColumnQualiferCellsList implements List<Cell> {

    private int minQualifier;
    private int maxQualifier;
    private int nonReservedRangeOffset;
    private final Cell[] array;
    private int numNonNullElements;
    private int firstNonNullElementIdx = -1;
    private static final int RESERVED_RANGE_SIZE = ENCODED_CQ_COUNTER_INITIAL_VALUE - ENCODED_EMPTY_COLUMN_NAME;
    // Used by iterators to figure out if the list was structurally modified.
    private int modCount = 0;
    private final QualifierEncodingScheme encodingScheme;

    public EncodedColumnQualiferCellsList(int minQ, int maxQ, QualifierEncodingScheme encodingScheme) {
        checkArgument(minQ <= maxQ, "Invalid arguments. Min: " + minQ
                + ". Max: " + maxQ);
        this.minQualifier = minQ;
        this.maxQualifier = maxQ;
        int size = 0;
        if (maxQ < ENCODED_CQ_COUNTER_INITIAL_VALUE) {
            size = RESERVED_RANGE_SIZE;
        } else if (minQ < ENCODED_CQ_COUNTER_INITIAL_VALUE) {
            size = (maxQ - minQ + 1);
        } else {
            size = RESERVED_RANGE_SIZE + (maxQ - minQ + 1);
        }
        this.array = new Cell[size];
        this.nonReservedRangeOffset = minQ > ENCODED_CQ_COUNTER_INITIAL_VALUE ? minQ  - ENCODED_CQ_COUNTER_INITIAL_VALUE : 0;
        this.encodingScheme = encodingScheme;
    }

    @Override
    public int size() {
        return numNonNullElements;
    }

    @Override
    public boolean isEmpty() {
        return numNonNullElements == 0;
    }

    @Override
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    @Override
    public Object[] toArray() {
        Object[] toReturn = new Object[numNonNullElements];
        int counter = 0;
        if (numNonNullElements > 0) {
            for (int i = 0; i < array.length; i++) {
                if (array[i] != null) {
                    toReturn[counter++] = array[i];
                }
            }
        }
        return toReturn;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        T[] toReturn =
                (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),
                    numNonNullElements);
        int counter = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] != null) {
                toReturn[counter++] = (T) array[i];
            }
        }
        return toReturn;
    }

    @Override
    public boolean add(Cell e) {
        if (e == null) {
            throw new NullPointerException();
        }
        int columnQualifier = encodingScheme.decode(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());
                
        checkQualifierRange(columnQualifier);
        int idx = getArrayIndex(columnQualifier);
        if (array[idx] == null) {
            numNonNullElements++;
        }
        array[idx] = e;
        if (firstNonNullElementIdx == -1) {
            firstNonNullElementIdx = idx;
        } else if (idx < firstNonNullElementIdx) {
            firstNonNullElementIdx = idx;
        }
        modCount++;
        /*
         * Note that we don't care about equality of the element being added with the element
         * already present at the index.
         */
        return true;
    }

    @Override
    public boolean remove(Object o) {
        if (o == null) {
            return false;
        }
        Cell e = (Cell) o;
        int i = 0;
        while (i < array.length) {
            if (array[i] != null && array[i].equals(e)) {
                array[i] = null;
                numNonNullElements--;
                if (numNonNullElements == 0) {
                    firstNonNullElementIdx = -1;
                } else if (firstNonNullElementIdx == i) {
                    // the element being removed was the first non-null element we knew
                    while (i < array.length && (array[i]) == null) {
                        i++;
                    }
                    if (i < array.length) {
                        firstNonNullElementIdx = i;
                    } else {
                        firstNonNullElementIdx = -1;
                    }
                }
                modCount++;
                return true;
            }
            i++;
        }
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        boolean containsAll = true;
        Iterator<?> itr = c.iterator();
        while (itr.hasNext()) {
            containsAll &= (indexOf(itr.next()) >= 0);
        }
        return containsAll;
    }

    @Override
    public boolean addAll(Collection<? extends Cell> c) {
        boolean changed = false;
        for (Cell cell : c) {
            if (c == null) {
                throw new NullPointerException();
            }
            changed |= add(cell);
        }
        return changed;
    }

    @Override
    public boolean addAll(int index, Collection<? extends Cell> c) {
        throwGenericUnsupportedOperationException();
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        Iterator<?> itr = c.iterator();
        boolean changed = false;
        while (itr.hasNext()) {
            changed |= remove(itr.next());
        }
        return changed;
    }

    @Override
    public boolean retainAll(Collection<?> collection) {
        boolean changed = false;
        // Optimize if the passed collection is an instance of EncodedColumnQualiferCellsList
        if (collection instanceof EncodedColumnQualiferCellsList) {
            EncodedColumnQualiferCellsList list = (EncodedColumnQualiferCellsList) collection;
            ListIterator<Cell> listItr = this.listIterator();
            while (listItr.hasNext()) {
                Cell cellInThis = listItr.next();
                int qualifier = encodingScheme.decode(cellInThis.getQualifierArray(),
                            cellInThis.getQualifierOffset(), cellInThis.getQualifierLength());
                try {
                    Cell cellInParam = list.getCellForColumnQualifier(qualifier);
                    if (cellInParam != null && cellInParam.equals(cellInThis)) {
                        continue;
                    }
                    listItr.remove();
                    changed = true;
                } catch (IndexOutOfBoundsException expected) {
                    // this could happen when the qualifier of cellInParam lies out of
                    // the range of this list.
                    listItr.remove();
                    changed = true;
                }
            }
        } else {
            throw new UnsupportedOperationException(
                    "Operation only supported for collections of type EncodedColumnQualiferCellsList");
        }
        return changed;
    }

    @Override
    public void clear() {
        for (int i = 0; i < array.length; i++) {
            array[i] = null;
        }
        firstNonNullElementIdx = -1;
        numNonNullElements = 0;
        modCount++;
    }

    @Override
    public Cell get(int index) {
        rangeCheck(index);
        int numNonNullElementsFound = 0;
        for (int i = firstNonNullElementIdx; i < array.length; i++) {
            if (array[i] != null) {
                numNonNullElementsFound++;
                if (numNonNullElementsFound == index + 1) {
                    return array[i];
                }
            }
        }
        throw new IllegalStateException("There was no element present in the list at index "
                + index + " even though number of elements in the list are " + size());
    }

    @Override
    public Cell set(int index, Cell e) {
        throwGenericUnsupportedOperationException();
        return null;
    }

    @Override
    public void add(int index, Cell element) {
        throwGenericUnsupportedOperationException();
    }

    @Override
    public Cell remove(int index) {
        throwGenericUnsupportedOperationException();
        return null;
    }

    @Override
    public int indexOf(Object o) {
        if (o == null || isEmpty()) {
            return -1;
        } else {
            int numNonNull = -1;
            for (int i = 0; i < array.length; i++) {
                if (array[i] != null) {
                    numNonNull++;
                }
                if (o.equals(array[i])) {
                    return numNonNull;
                }
            }
        }
        return -1;
    }

    @Override
    public int lastIndexOf(Object o) {
        if (o == null || isEmpty()) {
            return -1;
        }
        int lastIndex = numNonNullElements;
        for (int i = array.length - 1; i >= 0; i--) {
            if (array[i] != null) {
                lastIndex--;
            }
            if (o.equals(array[i])) {
                return lastIndex;
            }
        }
        return -1;
    }

    @Override
    public ListIterator<Cell> listIterator() {
        return new ListItr();
    }

    @Override
    public ListIterator<Cell> listIterator(int index) {
        throwGenericUnsupportedOperationException();
        return null;
    }

    @Override
    public List<Cell> subList(int fromIndex, int toIndex) {
        throwGenericUnsupportedOperationException();
        return null;
    }

    @Override
    public Iterator<Cell> iterator() {
        return new Itr();
    }

    public Cell getCellForColumnQualifier(byte[] qualifierBytes) {
        int columnQualifier = encodingScheme.decode(qualifierBytes);
        return getCellForColumnQualifier(columnQualifier);
    }
    
    public Cell getCellForColumnQualifier(byte[] qualifierBytes, int offset, int length) {
        int columnQualifier = encodingScheme.decode(qualifierBytes, offset, length);
        return getCellForColumnQualifier(columnQualifier);
    }
    
    private Cell getCellForColumnQualifier(int columnQualifier) {
        checkQualifierRange(columnQualifier);
        int idx = getArrayIndex(columnQualifier);
        Cell c = array[idx];
        return c;
    }

    public Cell getFirstCell() {
        if (firstNonNullElementIdx == -1) {
            throw new NoSuchElementException("No elements present in the list");
        }
        return array[firstNonNullElementIdx];
    }

    private void checkQualifierRange(int qualifier) {
        if (qualifier < ENCODED_CQ_COUNTER_INITIAL_VALUE) {
            return; // space in the array for reserved range is always allocated. 
        }
        if (qualifier < minQualifier || qualifier > maxQualifier) {
            throw new IndexOutOfBoundsException("Qualifier " + qualifier
                    + " is out of the valid range - (" + minQualifier + ", " + maxQualifier + ")");
        }
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size()) {
            throw new IndexOutOfBoundsException();
        }
    }

    private int getArrayIndex(int columnQualifier) {
        checkArgument(columnQualifier >= ENCODED_EMPTY_COLUMN_NAME);
        if (columnQualifier < ENCODED_CQ_COUNTER_INITIAL_VALUE) {
            return columnQualifier;
        }
        return columnQualifier - nonReservedRangeOffset;
    }

    private void throwGenericUnsupportedOperationException() {
        throw new UnsupportedOperationException(
                "Operation cannot be supported because it potentially violates the invariance contract of this list implementation");
    }

    private class Itr implements Iterator<Cell> {
        protected int nextIndex = 0;
        protected int lastRet = -1;
        protected int expectedModCount = modCount;
        
        private Itr() {
            moveForward(true);
        }

        @Override
        public boolean hasNext() {
            return nextIndex != -1;
        }

        @Override
        public Cell next() {
            checkForCoModification();
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            Cell next = array[nextIndex];
            lastRet = nextIndex;
            moveForward(false);
            modCount++;
            expectedModCount = modCount;
            return next;
        }

        @Override
        public void remove() {
            if (lastRet < 0) {
                throw new IllegalStateException();
            }
            checkForCoModification();
            array[lastRet] = null;
            lastRet = -1;
            numNonNullElements--;
            modCount++;
            expectedModCount = modCount;
        }

        protected void moveForward(boolean init) {
            int i = init ? 0 : nextIndex + 1;
            while (i < array.length && (array[i]) == null) {
                i++;
            }
            if (i < array.length) {
                nextIndex = i;
            } else {
                nextIndex = -1;
            }
        }
        
        protected void checkForCoModification() {
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }

    }

    private class ListItr extends Itr implements ListIterator<Cell> {
        private int previousIndex = -1;
        
        private ListItr() {
            moveForward(true);
        }

        @Override
        public boolean hasNext() {
            return nextIndex != -1;
        }

        @Override
        public boolean hasPrevious() {
            return previousIndex != -1;
        }

        @Override
        public Cell previous() {
            if (previousIndex == -1) {
                throw new NoSuchElementException();
            }
            checkForCoModification();
            lastRet = previousIndex;
            movePointersBackward();
            return array[lastRet];
        }

        @Override
        public int nextIndex() {
            return nextIndex;
        }

        @Override
        public int previousIndex() {
            return previousIndex;
        }

        @Override
        public void remove() {
            if (lastRet == nextIndex) {
                moveNextPointer(nextIndex);
            }
            super.remove();
            expectedModCount = modCount;
        }

        @Override
        public void set(Cell e) {
            if (lastRet == -1) {
                throw new IllegalStateException();
            }
            int columnQualifier = encodingScheme.decode(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());                    
            int idx = getArrayIndex(columnQualifier);
            if (idx != lastRet) {
                throw new IllegalArgumentException("Cell " + e + " with column qualifier "
                        + columnQualifier + " belongs at index " + idx
                        + ". It cannot be added at the position " + lastRet
                        + " to which the previous next() or previous() was pointing to.");
            }
            EncodedColumnQualiferCellsList.this.add(e);
            expectedModCount = modCount;
        }

        @Override
        public void add(Cell e) {
            throwGenericUnsupportedOperationException();
        }
        
        @Override
        protected void moveForward(boolean init) {
            if (!init) {
                previousIndex = nextIndex;
            }
            int i = init ? 0 : nextIndex + 1; 
            moveNextPointer(i);
        }

        private void moveNextPointer(int i) {
            while (i < array.length && (array[i]) == null) {
                i++;
            }
            if (i < array.length) {
                nextIndex = i;
            } else {
                nextIndex = -1;
            }
        }

        private void movePointersBackward() {
            nextIndex = previousIndex;
            int i = previousIndex - 1;
            movePreviousPointer(i);
        }

        private void movePreviousPointer(int i) {
            for (; i >= 0; i--) {
                if (array[i] != null) {
                    previousIndex = i;
                    break;
                }
            }
            if (i < 0) {
                previousIndex = -1;
            }
        }
    }

}
