/*******************************************************************************
 * Copyright (c) 2010, 2016 Ericsson, École Polytechnique de Montréal, and others
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License 2.0 which
 * accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Alexandre Montplaisir - Initial API and implementation
 *   Florian Wininger - Add Extension and Leaf Node
 *******************************************************************************/

package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.classic;

import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.eclipse.tracecompass.datastore.core.encoding.HTVarInt;
import org.eclipse.tracecompass.internal.provisional.datastore.core.condition.IntegerRangeCondition;
import org.eclipse.tracecompass.internal.provisional.datastore.core.condition.TimeRangeCondition;
import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTConfig;
import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTNode;
import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.ParentNode;
import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;

/**
 * A Core node is a first-level node of a History Tree which is not a leaf node.
 *
 * It extends HTNode by adding support for child nodes, and also extensions.
 *
 * @author Alexandre Montplaisir
 */
public final class CoreNode extends ParentNode {

    /** Nb. of children this node has */
    private int fNbChildren;

    /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */
    private int[] fChildren;

    /** Start times of each of the children (size = MAX_NB_CHILDREN) */
    private long[] fChildStart;
    private long[] fChildEnd;
    private int[] fChildMin;
    private int[] fChildMax;

    /**
     * Lock used to gate the accesses to the children arrays. Meant to be a
     * different lock from the one in {@link HTNode}.
     */
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(false);

    /**
     * Initial constructor. Use this to initialize a new EMPTY node.
     *
     * @param config
     *            Configuration of the History Tree
     * @param seqNumber
     *            The (unique) sequence number assigned to this particular node
     * @param parentSeqNumber
     *            The sequence number of this node's parent node
     * @param start
     *            The earliest timestamp stored in this node
     */
    public CoreNode(HTConfig config, int seqNumber, int parentSeqNumber,
            long start) {
        super(config, seqNumber, parentSeqNumber, start);
        fNbChildren = 0;
        int size = config.getMaxChildren();

        /*
         * We instantiate the two following arrays at full size right away,
         * since we want to reserve that space in the node's header.
         * "nbChildren" will tell us how many relevant entries there are in
         * those tables.
         */
        fChildren = new int[size];
        fChildStart = new long[size];
        Arrays.fill(fChildStart, Long.MIN_VALUE);
        fChildEnd = new long[size];
        Arrays.fill(fChildEnd, Long.MAX_VALUE);
        fChildMin = new int[size];
        fChildMax = new int[size];
        Arrays.fill(fChildMax, Integer.MAX_VALUE);
    }

    @Override
    protected void readSpecificHeader(ByteBuffer buffer) {
        int size = getConfig().getMaxChildren();

        fNbChildren = buffer.getInt();

        fChildren = new int[size];
        for (int i = 0; i < size; i++) {
            fChildren[i] = buffer.getInt();
        }

        fChildStart = new long[size];
        for (int i = 0; i < size; i++) {
            fChildStart[i] = HTVarInt.readLong(buffer);
        }

        fChildEnd = new long[size];
        for (int i = 0; i < size; i++) {
            fChildEnd[i] = HTVarInt.readLong(buffer);
        }

        fChildMin = new int[size];
        for (int i = 0; i < size; i++) {
            fChildMin[i] = buffer.getInt();
        }

        fChildMax = new int[size];
        for (int i = 0; i < size; i++) {
            fChildMax[i] = buffer.getInt();
        }
    }

    @Override
    protected void writeSpecificHeader(ByteBuffer buffer) {
        buffer.putInt(fNbChildren);

        /* Write the "children's sequence number" array */
        for (int child : fChildren) {
            buffer.putInt(child);
        }

        /* Write the "children's start times" array */
        for (long start : fChildStart) {
            HTVarInt.writeLong(buffer, start);
        }

        /* Write the "children's end times" array */
        for (long end : fChildEnd) {
            HTVarInt.writeLong(buffer, end);
        }

        /* Write the "children's min quark" array */
        for (int min : fChildMin) {
            buffer.putInt(min);
        }

        /* Write the "children's max quark" array */
        for (int max : fChildMax) {
            buffer.putInt(max);
        }
    }

    @Override
    public int getNbChildren() {
        rwl.readLock().lock();
        try {
            return fNbChildren;
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public int getChild(int index) {
        rwl.readLock().lock();
        try {
            return fChildren[index];
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public int getLatestChild() {
        rwl.readLock().lock();
        try {
            return fChildren[fNbChildren - 1];
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public long getChildStart(int index) {
        rwl.readLock().lock();
        try {
            return fChildStart[index];
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public long getChildEnd(int index) {
        rwl.readLock().lock();
        try {
            return fChildEnd[index];
        } finally {
            rwl.readLock().unlock();
        }
    }

    /**
     * Updates the end time for child node in header when closing branch
     *
     * @param child
     *            Child node whose bounds we must apply
     * @return -1 if child was not one of this node's children or index of the child
     *         within this node's children
     */
    public int closeChild(HTNode child) {
        int childSequenceNumber = child.getSequenceNumber();
        for (int i = 0; i < getNbChildren(); i++) {
            if (childSequenceNumber == getChild(i)) {
                fChildEnd[i] = child.getNodeEnd();
                fChildMin[i] = child.getMinQuark();
                fChildMax[i] = child.getMaxQuark();
                return i;
            }
        }
        return -1;
    }

    @Override
    public void linkNewChild(HTNode childNode) {
        rwl.writeLock().lock();
        try {
            if (fNbChildren >= getConfig().getMaxChildren()) {
                throw new IllegalStateException("Asked to link another child but parent already has maximum number of children"); //$NON-NLS-1$
            }

            fChildren[fNbChildren] = childNode.getSequenceNumber();
            fChildStart[fNbChildren] = childNode.getNodeStart();
            fNbChildren++;

        } finally {
            rwl.writeLock().unlock();
        }
    }

    @Override
    public Collection<Integer> selectNextChildren(long t) throws TimeRangeException {
        if (t < getNodeStart() || (isOnDisk() && t > getNodeEnd())) {
            throw new TimeRangeException("Requesting children outside the node's range: " + t); //$NON-NLS-1$
        }
        rwl.readLock().lock();
        try {
            List<Integer> next = new ArrayList<>();
            for (int i = 0; i < fNbChildren; i++) {
                if (t >= fChildStart[i] && t <= fChildEnd[i]) {
                    next.add(fChildren[i]);
                }
            }

            return next;
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public Collection<Integer> selectNextChildren(long t, int k) throws TimeRangeException {
        if (t < getNodeStart() || (isOnDisk() && t > getNodeEnd())) {
            throw new TimeRangeException("Requesting children outside the node's range: " + t); //$NON-NLS-1$
        }
        rwl.readLock().lock();
        try {
            List<Integer> next = new ArrayList<>();
            for (int i = 0; i < fNbChildren; i++) {
                if (t >= fChildStart[i] && t <= fChildEnd[i]
                        && k >= fChildMin[i] && k <= fChildMax[i]) {
                    next.add(fChildren[i]);
                }
            }

            return next;
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public void queueNextChildren2D(IntegerRangeCondition quarks, TimeRangeCondition times, Deque<Integer> queue, boolean reverse) {
        rwl.readLock().lock();
        try {
            /* Selectively search children */
            /*
             * Add all the nodes at the beginning of the queue for depth-first
             * search, the 'reverse' will specify which to insert first
             */
            Deque<Integer> toAdd = new ArrayDeque<>();
            for (int child = 0; child < fNbChildren; child++) {
                if (times.intersects(fChildStart[child], fChildEnd[child])
                        && quarks.intersects(fChildMin[child], fChildMax[child])) {
                    int potentialNextSeqNb = fChildren[child];
                    // Add them in the add list in the reverse order, so the
                    // order will be right in the final queue
                    if (!reverse) {
                        toAdd.addFirst(potentialNextSeqNb);
                    } else {
                        toAdd.add(potentialNextSeqNb);
                    }
                }
            }
            for (Integer seqNum : toAdd) {
                queue.addFirst(seqNum);
            }
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public NodeType getNodeType() {
        return NodeType.CORE;
    }

    @Override
    protected int getSpecificHeaderSize() {
        int maxChildren = getConfig().getMaxChildren();
        int ret = 0;
        /* 1x int (nbChildren) */
        ret += Integer.BYTES;
        for (int i = 0; i < getConfig().getMaxChildren(); i++) {
            ret += HTVarInt.getEncodedLengthLong(fChildStart[i]);
            ret += HTVarInt.getEncodedLengthLong(fChildEnd[i]);
        }
        /* MAX_NB * int ('children' table) */
        ret += Integer.BYTES * maxChildren;
        /* MAX_NB * quark ('childMin' and 'childMax' table) */
        ret += 2 * Integer.BYTES * maxChildren;
        return  ret;
    }

    @Override
    public int getMinQuark() {
        int min = super.getMinQuark();
        rwl.readLock().lock();
        try {
            for (int i = 0; i < fNbChildren; i++) {
                min = Integer.min(min, fChildMin[i]);
            }
            return min;
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public int getMaxQuark() {
        int max = super.getMaxQuark();
        rwl.readLock().lock();
        try {
            for (int i = 0; i < fNbChildren; i++) {
                max = Integer.max(max, fChildMax[i]);
            }
            return max;
        } finally {
            rwl.readLock().unlock();
        }
    }

    @Override
    public String toStringSpecific() {
        /* Only used for debugging, shouldn't be externalized */
        return String.format("Core Node, %d children %s", //$NON-NLS-1$
                fNbChildren, Arrays.toString(Arrays.copyOf(fChildren, fNbChildren)));
    }

}
