/******************************************************************************
* Copyright (C) 2015  Fabio Zadrozny and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Fabio Zadrozny <fabiofz@gmail.com>    - initial API and implementation
******************************************************************************/
package org.python.pydev.shared_core.string;

import org.eclipse.jface.text.rules.ICharacterScanner;
import org.python.pydev.shared_core.structure.FastStack;

public class StringScanner implements ICharacterScanner {

    private final String contents;
    private int offset;
    private final int length;

    public StringScanner(String contents) {
        this.contents = contents;
        this.length = contents.length();
    }

    @Override
    public int read() {
        if (offset < length) {
            // Most common case first.
            char ret = contents.charAt(offset);
            offset += 1;
            return ret;
        }
        if (offset == length) {
            offset++;
            return StringScanner.EOF; //EOF
        }
        // offset > length!
        throw new RuntimeException("Reading past EOF!");
    }

    // peek(0) reads the char at the current offset, peek(-1) reads the previous, peek(1) reads the next
    // and so on (all without changing the current offset).
    public int peek(int i) {
        int checkAt = offset + i;
        if (checkAt >= length || checkAt < 0) {
            return StringScanner.EOF;
        }
        return contents.charAt(checkAt);
    }

    @Override
    public void unread() {
        offset -= 1;
        if (offset < 0) {
            throw new RuntimeException("Reading before begin of stream.");
        }
    }

    public int getMark() {
        return offset;
    }

    public String getContents() {
        return this.contents;
    }

    final FastStack<char[]> endLevel = new FastStack<>(3);

    public void addLevelFinishingAt(char... endLevelChar) {
        endLevel.push(endLevelChar);
    }

    public void popLevel() {
        endLevel.pop();
    }

    public void setMark(int mark) {
        this.offset = mark;
    }

    public boolean isEndLevelChar(int c) {
        if (!endLevel.isEmpty()) {
            char[] peek = endLevel.peek();
            int len = peek.length;
            for (int i = 0; i < len; i++) {
                if (peek[i] == c) {
                    return true;
                }
            }
        }
        return false;
    }

    public int getLevel() {
        return endLevel.size();
    }

    @Override
    public char[][] getLegalLineDelimiters() {
        throw new AssertionError("Not implemented");
    }

    @Override
    public int getColumn() {
        throw new AssertionError("Not implemented");
    }

}