package org.stringtemplate.v4.test;

import org.junit.Test;
import org.stringtemplate.v4.*;
import org.stringtemplate.v4.misc.*;

import static org.junit.Assert.assertEquals;

public class TestScopes extends BaseTest {
    @Test public void testSeesEnclosingAttr() throws Exception {
        String templates =
            "t(x,y) ::= \"<u()>\"\n" +
            "u() ::= \"<x><y>\"";
        ErrorBuffer errors = new ErrorBuffer();
        writeFile(tmpdir, "t.stg", templates);
        STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
        group.setListener(errors);
        ST st = group.getInstanceOf("t");
        st.add("x", "x");
        st.add("y", "y");
        String result = st.render();

        String expectedError = "";
        assertEquals(expectedError, errors.toString());

        String expected = "xy";
        assertEquals(expected, result);
    }

    @Test public void testMissingArg() throws Exception {
        String templates =
            "t() ::= \"<u()>\"\n" +
            "u(z) ::= \"\"";
        ErrorBuffer errors = new ErrorBuffer();
        writeFile(tmpdir, "t.stg", templates);
        STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
        group.setListener(errors);
        ST st = group.getInstanceOf("t");
        String result = st.render();

        String expectedError = "context [/t] 1:1 passed 0 arg(s) to template /u with 1 declared arg(s)"+newline;
        assertEquals(expectedError, errors.toString());
    }

    @Test public void testUnknownAttr() throws Exception {
        String templates =
            "t() ::= \"<x>\"\n";
        ErrorBuffer errors = new ErrorBuffer();
        writeFile(tmpdir, "t.stg", templates);
        STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
        group.setListener(errors);
        ST st = group.getInstanceOf("t");
        String result = st.render();

        String expectedError = "context [/t] 1:1 attribute x isn't defined"+newline;
        assertEquals(expectedError, errors.toString());
    }

    @Test public void testArgWithSameNameAsEnclosing() throws Exception {
        String templates =
            "t(x,y) ::= \"<u(x)>\"\n" +
            "u(y) ::= \"<x><y>\"";
        ErrorBuffer errors = new ErrorBuffer();
        writeFile(tmpdir, "t.stg", templates);
        STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
        group.setListener(errors);
        ST st = group.getInstanceOf("t");
        st.add("x", "x");
        st.add("y", "y");
        String result = st.render();

        String expectedError = "";
        assertEquals(expectedError, errors.toString());

        String expected = "xx";
        assertEquals(expected, result);
        group.setListener(ErrorManager.DEFAULT_ERROR_LISTENER);
    }

    @Test public void testIndexAttrVisibleLocallyOnly() throws Exception {
        String templates =
            "t(names) ::= \"<names:{n | <u(n)>}>\"\n" +
            "u(x) ::= \"<i>:<x>\"";
        ErrorBuffer errors = new ErrorBuffer();
        writeFile(tmpdir, "t.stg", templates);
        STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
        group.setListener(errors);
        ST st = group.getInstanceOf("t");
        st.add("names", "Ter");
        String result = st.render();
        group.getInstanceOf("u").impl.dump();

        String expectedError = "t.stg 2:11: implicitly-defined attribute i not visible"+newline;
        assertEquals(expectedError, errors.toString());

        String expected = ":Ter";
        assertEquals(expected, result);
        group.setListener(ErrorManager.DEFAULT_ERROR_LISTENER);
    }

}
