package de.brightbyte.yates;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

public class YatesTemplateTest extends TestCase {

	public void testRender_values() throws YatesException {
		Map<String, Object> model = new HashMap<String, Object>(); //dummy
		model.put("foo", "foo");
		model.put("number", 23);
		model.put("float", 42.1);
		model.put("evil", "<ev&il>");
		
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("foo", "bar");
		m.put("xyzzy", "quux");
		model.put("map", m);
		
		YatesContext ctx = new YatesContext();
		ctx.setSetting("foo", "foo");
		ctx.setSharedValue("ixi", "pixi");

		YatesParameters param = new YatesParameters(ctx, null, model);
		
		YatesTemplate t;
		t = new YatesTemplate("");
		assertEquals("empty", "", t.render(param));
		
		t = new YatesTemplate("x y z");
		assertEquals("plain", "x y z", t.render(param));
		
		t = new YatesTemplate("{{$foo}}");
		assertEquals("value", "foo", t.render(param));

		t = new YatesTemplate("***{{$foo}}***");
		assertEquals("embedded value", "***foo***", t.render(param));

		t = new YatesTemplate("{{$foo.length}}");
		assertEquals("deep value", "3", t.render(param));

		t = new YatesTemplate("{{$map.xyzzy}}");
		assertEquals("nested value", "quux", t.render(param));

		t = new YatesTemplate("{{$map.property::size}}");
		assertEquals("axis value", "2", t.render(param));

		t = new YatesTemplate("{{$foo|x=y}}");
		assertEquals("param", "foo", t.render(param));

		t = new YatesTemplate("{{$foo | x = y,a=2,barf=false}}");
		assertEquals("more params", "foo", t.render(param));

		t = new YatesTemplate("{{$foo|x=\"}}\",y=\"|\"}}");
		assertEquals("nasty params", "foo", t.render(param));

		t = new YatesTemplate("{{$bar}}");
		assertEquals("missing value", "", t.render(param));

		t = new YatesTemplate("{{$bar|default=$foo}}");
		assertEquals("default value", "foo", t.render(param));

		t = new YatesTemplate("{{$settings.foo}}");
		assertEquals("setting value", "foo", t.render(param));

		t = new YatesTemplate("{{$ixi}}");
		assertEquals("shared value", "pixi", t.render(param));

		t = new YatesTemplate("{{$.number}}");
		assertEquals("number", "23", t.render(param));

		t = new YatesTemplate("{{$number}}");
		assertEquals("number", "23", t.render(param));

		t = new YatesTemplate("{{$float|format=\"%07.2f\"}}");
		assertEquals("format", "0042.10", t.render(param));

		t = new YatesTemplate("{{$evil}}");
		assertEquals("escape", "&lt;ev&amp;il&gt;", t.render(param));

		t = new YatesTemplate("{{$evil|escape=null}}");
		assertEquals("un-escaped", "<ev&il>", t.render(param));

		t = new YatesTemplate("{{$lbrace}}x{{$rbrace}}");
		assertEquals("lbrace/rbrace", "{x}", t.render(param));
	}

	public void testRender_templates() throws YatesException {
		Map<String, Object> model = new HashMap<String, Object>(); //dummy
		model.put("moo", "moo");
		model.put("five", 5);
		model.put("number", 23);
		
		YatesContext ctx = new YatesContext();
		ctx.setSetting("foo", "foo");
		ctx.setMacro("foo", new LiteralMacro("<FOO>"));
		ctx.setMacro("bar", new YatesTemplate("bar: {{$number}}"));
		
		YatesParameters param = new YatesParameters(ctx, null, model);

		YatesTemplate t;
		t = new YatesTemplate("{{foo}}");
		assertEquals("template", "<FOO>", t.render(param));

		t = new YatesTemplate("{{ bar | &number = $five }}");
		assertEquals("template param override", "bar: 5", t.render(param));
		
		t = new YatesTemplate("{{foo|escape=$settings.escaper}}");
		assertEquals("force escape", "&lt;FOO&gt;", t.render(param));
		
		t = new YatesTemplate("xxx {{foo}}yyy");
		assertEquals("embedded", "xxx <FOO>yyy", t.render(param));
	}

	public void testRender_blocks() throws YatesException {
		Map<String, Object> model = new HashMap<String, Object>(); //dummy
		
		List<String> stuff = new ArrayList<String>();
		stuff.add("one");
		stuff.add("two");
		stuff.add("three");
		model.put("stuff", stuff);
		model.put("yes", 1);
		model.put("no", false);
		
		YatesContext ctx = new YatesContext();
		ctx.setMacro("record", new YatesTemplate(" ({{$.}}) "));
		ctx.setMacro("echo", new YatesTemplate("({{_}}|{{$_}})"));
		ctx.setMacro("tags", new LiteralMacro("<a><b><i>"));
		ctx.setMacro("foo", new LiteralMacro("FOO"));

		ctx.setSharedValue("htmlEscape", YatesHtml.escaper);
		
		YatesParameters param = new YatesParameters(ctx, null, model);
		
		YatesTemplate t;
		String s;
		
		t = new YatesTemplate("-{{foreach|for=$stuff, use=record, between=\"|\"}}-");
		s = t.render(param);
		assertEquals("ugly foreach", "- (one) | (two) | (three) -", s);

		t = new YatesTemplate("-{{foreach|for=$stuff, between=\"|\"|[{{record}}]}}-");
		s = t.render(param);
		assertEquals("pretty foreach", "-[ (one) ]|[ (two) ]|[ (three) ]-", s);

		t = new YatesTemplate("-{{foreach|for=$stuff, between=\"|\"|[{{$.}}]}}-");
		s = t.render(param);
		assertEquals("direct foreach", "-[one]|[two]|[three]-", s);

		t = new YatesTemplate("-{{foreach|for=$stuff, between=\"|\" `[{{$.}}]`}}-");
		s = t.render(param);
		assertEquals("quotes foreach", "-[{{$.}}]|[{{$.}}]|[{{$.}}]-", s);

		t = new YatesTemplate("{{block|use=foo}}");
		s = t.render(param);
		assertEquals("ugly block", "FOO", s);

		t = new YatesTemplate("{{block|if=$yes|yes}}");
		s = t.render(param);
		assertEquals("if yes block", "yes", s);

		t = new YatesTemplate("{{block|if=$no|no}}");
		s = t.render(param);
		assertEquals("if no block", "", s);

		t = new YatesTemplate("{{block|if=$yes, equals=1|one}}");
		s = t.render(param);
		assertEquals("if yes equals 1", "one", s);

		t = new YatesTemplate("{{block|if=$yes, equals=2|two}}");
		s = t.render(param);
		assertEquals("if yes equals 2", "", s);

		t = new YatesTemplate("{{block|if=$xxx|xxx}}");
		s = t.render(param);
		assertEquals("if null", "", s);

		t = new YatesTemplate("{{|escape=$htmlEscape|<br/>{{tags}}}}");
		s = t.render(param);
		assertEquals("escape anon block", "&lt;br/&gt;&lt;a&gt;&lt;b&gt;&lt;i&gt;", s);

		t = new YatesTemplate("{{|escape=$htmlEscape`<br/>{{tags}}`}}");
		s = t.render(param);
		assertEquals("escape quoted anon block", "&lt;br/&gt;{{tags}}", s);

		t = new YatesTemplate("foo {{%%}} bar");
		s = t.render(param);
		assertEquals("empty comment", "foo  bar", s);

		t = new YatesTemplate("foo {{% foo %}} bar");
		s = t.render(param);
		assertEquals("simple comment", "foo  bar", s);

		t = new YatesTemplate("foo {{%{{* yadda *}}%}} bar");
		s = t.render(param);
		assertEquals("nasty comment", "foo  bar", s);

		t = new YatesTemplate("- {{\"foo {{tags}} {{`bar`}} {{* blubb *}}\"}} -");
		s = t.render(param);
		assertEquals("complex quoted", "- foo {{tags}} {{`bar`}} {{* blubb *}} -", s);

		t = new YatesTemplate("{{echo||-{{tags}}-}}");
		s = t.render(param);
		assertEquals("recursive echo", "(-<a><b><i>-|-&lt;a&gt;&lt;b&gt;&lt;i&gt;-)", s);
		
		t = new YatesTemplate("{{|a=b ` x `}}");
		s = t.render(param);
		assertEquals("quoted blanks in block", " x ", s);
	}
	
}
