package io.collap.bryg.compiler.context;

import io.collap.bryg.compiler.bytecode.BrygMethodVisitor;
import io.collap.bryg.compiler.expression.RootScope;
import io.collap.bryg.compiler.expression.Scope;
import io.collap.bryg.compiler.library.Library;
import io.collap.bryg.compiler.parser.StandardVisitor;
import io.collap.bryg.compiler.resolver.ClassResolver;
import io.collap.bryg.compiler.type.Type;
import io.collap.bryg.model.Model;

import java.io.Writer;
import java.util.Stack;

public class Context {

    private StandardVisitor parseTreeVisitor;
    private BrygMethodVisitor methodVisitor;
    private Scope rootScope = new RootScope ();
    private Library library;
    private ClassResolver classResolver;

    //
    //  Compiler states
    //

    /**
     * The current scope is the scope each node resides in at its creation.
     */
    private Scope currentScope = rootScope;

    /**
     * When the stack has at least one element, any print output is discarded.
     * This is a Stack instead of a boolean, because 'discard' functions can be nested.
     * The element type has no meaning.
     */
    private Stack<Integer> discardStack = new Stack<> ();

    public Context (BrygMethodVisitor methodVisitor, Library library, ClassResolver classResolver) {
        this.parseTreeVisitor = new StandardVisitor ();
        this.methodVisitor = methodVisitor;
        this.library = library;
        this.classResolver = classResolver;

        /* Register parameters in the correct order. */
        rootScope.registerVariable ("this", null); // TODO: Proper type.
        rootScope.registerVariable ("writer", new Type (Writer.class));
        rootScope.registerVariable ("model", new Type (Model.class));

        /* Set context instance for the parameters. */
        parseTreeVisitor.setContext (this);
        methodVisitor.setContext (this);
    }

    public boolean shouldDiscardPrintOutput () {
        return !discardStack.isEmpty ();
    }

    public void pushDiscard () {
        discardStack.push (0);
    }

    public void popDiscard () {
        discardStack.pop ();
    }

    public StandardVisitor getParseTreeVisitor () {
        return parseTreeVisitor;
    }

    public BrygMethodVisitor getMethodVisitor () {
        return methodVisitor;
    }

    public Scope getRootScope () {
        return rootScope;
    }

    public Library getLibrary () {
        return library;
    }

    public ClassResolver getClassResolver () {
        return classResolver;
    }

    public Scope getCurrentScope () {
        return currentScope;
    }

    public void setCurrentScope (Scope currentScope) {
        this.currentScope = currentScope;
    }

}

@@ -458,32 +458,8 @@
 ter;
-%0Aimport java.util.Stack;
 %0A%0Apu
@@ -885,47 +885,40 @@
   * 
-When
+If
  the 
-stack has at least one element
+counter is greater than 1
 , an
@@ -963,21 +963,23 @@
 is is a 
-Stack
+counter
  instead
@@ -1046,106 +1046,42 @@
    *
- The element type has no meaning.%0A     */%0A    private Stack%3CInteger%3E discardStack = new Stack%3C%3E ()
+/%0A    private int discardsOpen = 0
 ;%0A%0A 
@@ -1844,32 +1844,24 @@
 urn 
-!
 discard
-Stack.isEmpty ()
+sOpen %3E 0
 ;%0A  
@@ -1910,29 +1910,22 @@
     
+++
 discard
-Stack.push (0)
+sOpen
 ;%0A  
@@ -1973,27 +1973,22 @@
     
+--
 discard
-Stack.pop ()
+sOpen
 ;%0A  

Replace Stack with counter, as the element is irrelevant.