/*
 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.jgss;

import org.ietf.jgss.MessageProp;
import java.util.LinkedList;

/**
 * A utility class that implements a number list that keeps track of which
 * tokens have arrived by storing their token numbers in the list. It helps
 * detect old tokens, out of sequence tokens, and duplicate tokens.
 *
 * Each element of the list is an interval [a, b]. Its existence in the
 * list implies that all token numbers in the range a, a+1, ..., b-1, b
 * have arrived. Gaps in arrived token numbers are represented by the
 * numbers that fall in between two elements of the list. eg. {[a,b],
 * [c,d]} indicates that the token numbers b+1, ..., c-1 have not arrived
 * yet.
 *
 * The maximum number of intervals that we keep track of is
 * MAX_INTERVALS. Thus if there are too many gaps, then some of the older
 * sequence numbers are deleted from the list. The earliest sequence number
 * that exists in the list is the windowStart. The next expected sequence
 * number, or expectedNumber, is one greater than the latest sequence
 * number in the list.
 *
 * The list keeps track the first token number that should have arrived
 * (initNumber) so that it is able to detect if certain numbers occur after
 * the first valid token number but before windowStart. That would happen
 * if the number of elements (intervals) exceeds MAX_INTERVALS and some
 * initial elements had  to be deleted.
 *
 * The working of the list is optimized for the normal case where the
 * tokens arrive in sequence.
 *
 * @author Mayank Upadhyay
 * @since 1.4
 */
public class TokenTracker {

    static final int MAX_INTERVALS = 5;

    private int initNumber;
    private int windowStart;
    private int expectedNumber;

    private int windowStartIndex = 0;

    private LinkedList<Entry> list = new LinkedList<Entry>();

    public TokenTracker(int initNumber) {

        this.initNumber = initNumber;
        this.windowStart = initNumber;
        this.expectedNumber = initNumber;

        // Make an entry with one less than the expected first token
        Entry entry = new Entry(initNumber-1);

        list.add(entry);
    }

    /**
     * Returns the index for the entry into which this number will fit. If
     * there is none, it returns the index of the last interval
     * which precedes this number. It returns -1 if the number needs to be
     * a in a new interval ahead of the whole list.
     */
    private int getIntervalIndex(int number) {
        Entry entry = null;
        int i;
        // Start from the rear to optimize for the normal case
        for (i = list.size() - 1; i >= 0; i--) {
            entry = list.get(i);
            if (entry.compareTo(number) <= 0)
                break;
        }
        return i;
    }

    /**
     * Sets the sequencing and replay information for the given token
     * number.
     *
     * The following represents the number line with positions of
     * initNumber, windowStart, expectedNumber marked on it. Regions in
     * between them show the different sequencing and replay state
     * possibilites for tokens that fall in there.
     *
     *  (1)      windowStart
     *           initNumber               expectedNumber
     *              |                           |
     *           ---|---------------------------|---
     *          GAP |    DUP/UNSEQ              | GAP
     *
     *
     *  (2)       initNumber   windowStart   expectedNumber
     *              |               |              |
     *           ---|---------------|--------------|---
     *          GAP |      OLD      |  DUP/UNSEQ   | GAP
     *
     *
     *  (3)                                windowStart
     *           expectedNumber            initNumber
     *              |                           |
     *           ---|---------------------------|---
     *    DUP/UNSEQ |           GAP             | DUP/UNSEQ
     *
     *
     *  (4)      expectedNumber    initNumber   windowStart
     *              |               |              |
     *           ---|---------------|--------------|---
     *    DUP/UNSEQ |        GAP    |    OLD       | DUP/UNSEQ
     *
     *
     *
     *  (5)      windowStart   expectedNumber    initNumber
     *              |               |              |
     *           ---|---------------|--------------|---
     *          OLD |    DUP/UNSEQ  |     GAP      | OLD
     *
     *
     *
     * (This analysis leaves out the possibility that expectedNumber passes
     * initNumber after wrapping around. That may be added later.)
     */
    synchronized public final void getProps(int number, MessageProp prop) {

        boolean gap = false;
        boolean old = false;
        boolean unsequenced = false;
        boolean duplicate = false;

        // System.out.println("\n\n==========");
        // System.out.println("TokenTracker.getProps(): number=" + number);
        // System.out.println(toString());

        int pos = getIntervalIndex(number);
        Entry entry = null;
        if (pos != -1)
            entry = list.get(pos);

        // Optimize for the expected case:

        if (number == expectedNumber) {
            expectedNumber++;
        } else {

            // Next trivial case is to check for duplicate
            if (entry != null && entry.contains(number))
                duplicate = true;
            else {

                if (expectedNumber >= initNumber) {

                    // Cases (1) and (2)

                    if (number > expectedNumber) {
                        gap = true;
                    } else if (number >= windowStart) {
                        unsequenced = true;
                    } else if (number >= initNumber) {
                        old = true;
                    } else {
                        gap = true;
                    }
                } else {

                    // Cases (3), (4) and (5)

                    if (number > expectedNumber) {
                        if (number < initNumber) {
                            gap = true;
                        } else if (windowStart >= initNumber) {
                            if (number >= windowStart) {
                               unsequenced = true;
                            } else
                                old = true;
                        } else {
                            old = true;
                        }
                    } else if (windowStart > expectedNumber) {
                        unsequenced = true;
                    } else if (number < windowStart) {
                        old = true;
                    } else
                        unsequenced = true;
                }
            }
        }

        if (!duplicate && !old)
            add(number, pos);

        if (gap)
            expectedNumber = number+1;

        prop.setSupplementaryStates(duplicate, old, unsequenced, gap,
                                    0, null);

        // System.out.println("Leaving with state:");
        // System.out.println(toString());
        // System.out.println("==========\n");
    }

    /**
     * Adds the number to the list just after the entry that is currently
     * at position prevEntryPos. If prevEntryPos is -1, then the number
     * will begin a new interval at the front of the list.
     */
    private void add(int number, int prevEntryPos) {

        Entry entry;
        Entry entryBefore = null;
        Entry entryAfter = null;

        boolean appended = false;
        boolean prepended = false;

        if (prevEntryPos != -1) {
            entryBefore = list.get(prevEntryPos);

            // Can this number simply be added to the previous interval?
            if (number == (entryBefore.getEnd() + 1)) {
                entryBefore.setEnd(number);
                appended = true;
            }
        }

        // Now check the interval that follows this number

        int nextEntryPos = prevEntryPos + 1;
        if ((nextEntryPos) < list.size()) {
            entryAfter = list.get(nextEntryPos);

            // Can this number simply be added to the next interval?
            if (number == (entryAfter.getStart() - 1)) {
                if (!appended) {
                    entryAfter.setStart(number);
                } else {
                    // Merge the two entries
                    entryAfter.setStart(entryBefore.getStart());
                    list.remove(prevEntryPos);
                    // Index of any entry following this gets decremented
                    if (windowStartIndex > prevEntryPos)
                        windowStartIndex--;
                }
                prepended = true;
            }
        }

        if (prepended || appended)
            return;

        /*
         * At this point we know that the number will start a new interval
         * which needs to be added to the list. We might have to recyle an
         * older entry in the list.
         */

        if (list.size() < MAX_INTERVALS) {
            entry = new Entry(number);
            if (prevEntryPos  < windowStartIndex)
                windowStartIndex++; // due to the insertion which will happen
        } else {
            /*
             * Delete the entry that marks the start of the current window.
             * The marker will automatically point to the next entry in the
             * list when this happens. If the current entry is at the end
             * of the list then set the marker to the start of the list.
             */
            int oldWindowStartIndex = windowStartIndex;
            if (windowStartIndex == (list.size() - 1))
                windowStartIndex = 0;

            entry = list.remove(oldWindowStartIndex);
            windowStart = list.get(windowStartIndex).getStart();
            entry.setStart(number);
            entry.setEnd(number);

            if (prevEntryPos >= oldWindowStartIndex) {
                prevEntryPos--; // due to the deletion that just happened
            } else {
                /*
                 * If the start of the current window just moved from the
                 * end of the list to the front of the list, and if the new
                 * entry will be added to the front of the list, then
                 * the new entry is the actual window start.
                 * eg, Consider { [-10, -8], ..., [-6, -3], [3, 9]}. In
                 * this list, suppose the element [3, 9] is the start of
                 * the window and has to be deleted to make place to add
                 * [-12, -12]. The resultant list will be
                 * {[-12, -12], [-10, -8], ..., [-6, -3]} and the new start
                 * of the window should be the element [-12, -12], not
                 * [-10, -8] which succeeded [3, 9] in the old list.
                 */
                if (oldWindowStartIndex != windowStartIndex) {
                    // windowStartIndex is 0 at this point
                    if (prevEntryPos == -1)
                        // The new entry is going to the front
                        windowStart = number;
                } else {
                    // due to the insertion which will happen:
                    windowStartIndex++;
                }
            }
        }

        // Finally we are ready to actually add to the list at index
        // 'prevEntryPos+1'

        list.add(prevEntryPos+1, entry);
    }

    public String toString() {
        StringBuffer buf = new StringBuffer("TokenTracker: ");
        buf.append(" initNumber=").append(initNumber);
        buf.append(" windowStart=").append(windowStart);
        buf.append(" expectedNumber=").append(expectedNumber);
        buf.append(" windowStartIndex=").append(windowStartIndex);
        buf.append("\n\tIntervals are: {");
        for (int i = 0; i < list.size(); i++) {
            if (i != 0)
                buf.append(", ");
            buf.append(list.get(i).toString());
        }
        buf.append('}');
        return buf.toString();
    }

    /**
     * An entry in the list that represents the sequence of received
     * tokens. Each entry is actaully an interval of numbers, all of which
     * have been received.
     */
    class Entry {

        private int start;
        private int end;

        Entry(int number) {
            start = number;
            end = number;
        }

        /**
         * Returns -1 if this interval represented by this entry precedes
         * the number, 0 if the the number is contained in the interval,
         * and -1 if the interval occurs after the number.
         */
        final int compareTo(int number) {
            if (start > number)
                return 1;
            else if (end < number)
                return -1;
            else
                return 0;
        }

        final boolean contains(int number) {
            return (number >= start &&
                    number <= end);
        }

        final void append(int number) {
            if (number == (end + 1))
                end = number;
        }

        final void setInterval(int start, int end) {
            this.start = start;
            this.end = end;
        }

        final void setEnd(int end) {
            this.end = end;
        }

        final void setStart(int start) {
            this.start = start;
        }

        final int getStart() {
            return start;
        }

        final int getEnd() {
            return end;
        }

        public String toString() {
            return ("[" + start + ", " + end + "]");
        }

    }
}
