/*
 * Copyright (C) 2009-2010 Mathias Doenitz
 *
 * 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 org.parboiled.support;

import org.jetbrains.annotations.NotNull;

/**
 * Abstraction of a simple char[] buffer holding the input text to be parsed.
 */
public interface InputBuffer {

    /**
     * Returns the number of characters in the buffer.
     *
     * @return the number of characters
     */
    int getLength();

    /**
     * Returns the character at the given index. If the index is invalid the method returns {@link org.parboiled.support.Characters#EOI}.
     *
     * @param index the index
     * @return the character at the given index or Chars.EOI.
     */
    char charAt(int index);

    /**
     * Returns the line and column number of the character with the given index encapsulated in a {@link org.parboiled.support.InputBuffer.Position}
     * object. The very first character has the line number 1 and the column number 1.
     *
     * @param index the index of the character to get the line number of
     * @return the line number
     */
    Position getPosition(int index);

    /**
     * Constructs a new {@link String} containing all characters with the given line number except for the trailing
     * newline.
     *
     * @param lineNumber the line number to get
     * @return the string
     */
    String extractLine(int lineNumber);

    /**
     * Constructs a new {@link String} from all character between the given indices.
     * Invalid indices are automatically adjusted to their respective boundary.
     *
     * @param start the start index (inclusively)
     * @param end   the end index (exclusively)
     * @return a new String (non-interned)
     */
    @NotNull
    String extract(int start, int end);

    /**
     * Simple container class for a line/column position in the input text.
     */
    public static class Position {
        public final int line;
        public final int column;

        public Position(int line, int column) {
            this.line = line;
            this.column = column;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Position)) return false;
            Position position = (Position) o;
            return column == position.column && line == position.line;

        }

        @Override
        public int hashCode() {
            int result = line;
            result = 31 * result + column;
            return result;
        }

        @Override
        public String toString() {
            return "Position{" +
                    "line=" + line +
                    ", column=" + column +
                    '}';
        }
    }
}
