/*
 * Copyright (c) 2015-2019 Dzikoysk
 *
 * 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.panda_lang.panda.framework.design.interpreter.token.stream;

import org.panda_lang.panda.framework.design.interpreter.token.TokenRepresentation;
import org.panda_lang.panda.framework.design.interpreter.token.snippet.Snippet;

public interface SourceStream {

    /**
     * Read the next token
     *
     * @return the next token
     */
    TokenRepresentation read();

    /**
     * Read the specified amount of tokens
     *
     * @param length amount of tokens to read
     * @return the read tokens
     */
    Snippet read(int length);

    /**
     * Read the rest of the current line
     *
     * @return the rest of the source at the current line
     */
    Snippet readLineResidue();

    /**
     * Restore the previous source (before the read operation)
     *
     * @return the current instance with restored content
     */
    SourceStream restoreCachedSource();

    /**
     * Override cached source
     *
     * @return the current instance
     */
    SourceStream updateCachedSource();

    /**
     * Replace content with the specified source
     *
     * @param source the content
     * @return the current instance with updated source
     */
    SourceStream update(Snippet source);

    /**
     * Get original source used to create the stream
     *
     * @return the original source
     */
    Snippet getOriginalSource();

    /**
     * Get current source as Tokens
     *
     * @return the current content wrapped in Tokens
     */
    Snippet toSnippet();

    /**
     * Read the same amount of tokens as in the provided snippet
     *
     * @param source the source to compare with
     * @return the read source
     */
    default Snippet readDifference(Snippet source) {
        return read(source.size());
    }

    /**
     * Check if the source has available content
     *
     * @return true if source contains available for read content
     */
    default boolean hasUnreadSource() {
        return !toSnippet().isEmpty();
    }

    /**
     * Get current line
     *
     * @return if there is no available source, the method returns -2, otherwise returns the number of current line
     */
    default int getCurrentLine() {
        return hasUnreadSource() ? toSnippet().getFirst().getLine() : -2;
    }

    /**
     * Get the amount of read tokens
     *
     * @return the amount of read tokens
     */
    default int getReadLength() {
        return getOriginalLength() - getUnreadLength();
    }

    /**
     * Get the amount of unread tokens
     *
     * @return the amount of unread tokens
     */
    default int getUnreadLength() {
        return toSnippet().size();
    }

    /**
     * Get the original length of source
     *
     * @return the original length of source
     */
    default int getOriginalLength() {
        return getOriginalSource().size();
    }

}

@@ -1181,134 +1181,115 @@
 the 
-rest of the current line%0A     *%0A     * @return the rest of the source at the current line%0A     */%0A    Snippet readLineResidue(
+specified amount of tokens and dispose result (it won't create snippet)%0A     */%0A    void dispose(int length
 );%0A%0A
@@ -1309,235 +1309,87 @@
 * Re
-store
+ad
  the 
-p
 re
-vious source (before the read operation)%0A     *%0A     * @return the current instance with restored content%0A     */%0A    SourceStream restoreCachedSource();%0A%0A    /**%0A     * Override cached source%0A     *%0A     * @return
+st of the current line%0A     *%0A     * @return the rest of the source at
  the
@@ -1397,23 +1397,19 @@
 current 
+l
 in
-stanc
 e%0A     *
@@ -1419,130 +1419,82 @@
    S
-ourceStream updateCachedSource();%0A%0A    /**%0A     * Replace content with the specified source%0A     *%0A     * @param source th
+nippet readLineResidue();%0A%0A    /**%0A     * Check if the source has availabl
 e co
@@ -1495,24 +1495,31 @@
 ble content%0A
+     *%0A
      * @retu
@@ -1526,94 +1526,94 @@
 rn t
-he current instance with updated source%0A     */%0A    SourceStream update(Snippet s
+rue if source contains available for read content%0A     */%0A    boolean hasUnreadS
 ource
+(
 );%0A%0A
@@ -1761,633 +1761,8 @@
 );%0A%0A
-    /**%0A     * Get current source as Tokens%0A     *%0A     * @return the current content wrapped in Tokens%0A     */%0A    Snippet toSnippet();%0A%0A    /**%0A     * Read the same amount of tokens as in the provided snippet%0A     *%0A     * @param source the source to compare with%0A     * @return the read source%0A     */%0A    default Snippet readDifference(Snippet source) %7B%0A        return read(source.size());%0A    %7D%0A%0A    /**%0A     * Check if the source has available content%0A     *%0A     * @return true if source contains available for read content%0A     */%0A    default boolean hasUnreadSource() %7B%0A        return !toSnippet().isEmpty();%0A    %7D%0A%0A
     
@@ -2197,22 +2197,29 @@
 Original
-Length
+Source().size
 () - get
@@ -2447,184 +2447,125 @@
 Get 
-the original length of source%0A     *%0A     * @return the original length of source%0A     */%0A    default int getOriginalLength() %7B%0A        return getOriginalSource().size();%0A    %7D
+current source as Tokens%0A     *%0A     * @return the current content wrapped in Tokens%0A     */%0A    Snippet toSnippet();
 %0A%0A%7D%0A

Improve SourceStream API and immutability (Resolves #157)