/*
 * Copyright(C) 2007 t-doi,All rights reserved.
 *
 * 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.amritaj;

import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.amritaj.html.HtmlNode;
import org.amritaj.html.impl.TextNodeImpl;

import junit.framework.TestCase;

public class TemplateTextTest extends TestCase {
	private String templateString = null;
	private Map<String, Object> data = null;
	private Object data2 = null;
	private String result = null;
	private String expected = null;
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
	}
	
	public void testNormalExpand() {
		templateString = "<p id=\"body\"></p>";
		
		data2 = new HelloWorldPage();
		
		expected = "<p>Hello AmritaJ!</p>";
		
		scenario2();
		
		verify();
	}
	
	public void testNormatExpandWithMap() {
		templateString = "<p id=\"body\"></p>";
		data = new HashMap<String, Object>();
		data.put("body", "Hello World!");
		expected = "<p>Hello World!</p>";
		
		scenario();
		verify();
	}
	
	public void testArrayDataExpand() {
		templateString = "<span id=\"array_data\"> </span>";
		data = new HashMap<String, Object>();
		data.put("array_data", new String[]{"1", "2", "3"});
		expected = "123";
		
		scenario();
		verify();
	}

	public void testArrayDataExpandInteger() {
		templateString = "<span id=\"array_data\"> </span>";
		data = new HashMap<String, Object>();
		data.put("array_data", new Integer[]{1, 2, 3});
		expected = "123";
		
		scenario();
		verify();
	}
	
	public void testPrimitiveArrayDataExpandInteger() {
		templateString = "<span id=\"array_data\"> </span>";
		data = new HashMap<String, Object>();
		data.put("array_data", new int[]{1, 2, 3});
		expected = "123";
		
		scenario();
		verify();
	}
	
	public void testNestedStruct() {
		templateString = "<P id=\"nested_struct\">" +
				"<span id=\"hours\" />:<span id=\"minutes\" />:<span id=\"seconds\" />" +
				"</P>";
		data = new HashMap<String, Object>();
		data.put("nested_struct", new Date(2005, 2, 23, 4, 5, 6));
		expected = "<P>4:5:6</P>";
		
		scenario();
		verify();
	}
	
	public void testNestedStructArray() {
		templateString = "<P id=\"nested_struct\">" +
				"<span id=\"date\" />" +
				"</P>";
		data = new HashMap<String, Object>();
		data.put("nested_struct", new Date[]{new Date(2005, 2, 23, 4, 5, 6),new Date(2005, 2, 24, 4, 5, 6)});
		expected = "<P>23</P><P>24</P>";
		
		scenario();
		verify();
	}		
	
	public void testAttributeReplace() {
		templateString = "<a id=\"attribute_replace\">Amrita2</a>";
		data = new HashMap<String, Object>();
		AttrArray a = new AttrArray();
		a.add("href", "http://amrita2.rubyforge.org/");
		data.put("attribute_replace", a);
		expected = "<a href=\"http://amrita2.rubyforge.org/\">Amrita2</a>";
		
		scenario();
		verify();
	}
	
	public void testAttributeReplace2() {
		templateString = "<a id=\"attribute_replace\">Amrita2</a>";
		data = new HashMap<String, Object>();
		AttrArray a = new AttrArray();
		a.add("href", "http://amrita2.rubyforge.org/");
		a.setReplaceValue("Ruby Home Page");
		data.put("attribute_replace", a);
		expected = "<a href=\"http://amrita2.rubyforge.org/\">Ruby Home Page</a>";
		
		scenario();
		verify();
	}
	
	public void testAttributeReplaceMix() {
		templateString = "<a id=\"attribute_replace\" class=\"hoge\">Amrita2</a>";
		data = new HashMap<String, Object>();
		AttrArray a = new AttrArray();
		a.add("href", "http://amrita2.rubyforge.org/");
		data.put("attribute_replace", a);
		expected = "<a href=\"http://amrita2.rubyforge.org/\" class=\"hoge\">Amrita2</a>";
		
		scenario();
		verify();
	}
	
	public void test2NestedPojo() {
		templateString = "<p id=\"date\">" +
		"<span id=\"date\"/>" +
		"</p>";
		
		data2 = new Nested2();
		
		expected = "<p>23</p>";
		
		scenario2();
		verify();
	}
	
	public void test3NestedPojo() {
		templateString = "<p id=\"nested1\">" +
		"<span id=\"nested2\">" +
		"<span id=\"date\"><span id=\"date\"/></span> <span id=\"array\"/>" +
		"</span>" +
		"</p>";
		
		data2 = new HogePage();
		
		expected = "<p>23 123</p>";
		
		scenario2();
		verify();
	}
	public void testNoIDHtml() {
		templateString = "<html><body>Hello World!</body></html>";
		
		data = null;
		
		expected = "<html><body>Hello World!</body></html>";
		
		scenario();
		verify();
	}	
	
	public void testAmritaTypeLink() {
		templateString = "<a id=\"a2\" amrita:type=\"link\">Amrita2</a>";
		
		data = new HashMap<String, Object>();
		
		data.put("a2", "http://amrita2.rubyforge.org/");
		
		expected = "<a href=\"http://amrita2.rubyforge.org/\">Amrita2</a>";
		
		scenario();
		verify();
	}

	public void testAmritaTypeUseArgs() {
		templateString = "<a id=\"rubytalk\" amrita:type=\"use_args\" href=\"http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/$1\">[ruby-talk:$1]</a>";
		
		data = new HashMap<String, Object>();
		
		data.put("rubytalk", "132204");
		
		expected = "<a href=\"http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/132204\" >[ruby-talk:132204]</a>";
		
		scenario();
		verify();
	}


	public void testAmritaTypeUseArgsTuple() {
		templateString = "<a id=\"raa\" amrita:type=\"use_args\" href=\"http://raa.ruby-lang.org/list.rhtml?name=$1\">[$2]</a>";
		
		data = new HashMap<String, Object>();
		
		Tuple t = new Tuple();
		t.addReplaceValue("amrita");
		t.addReplaceValue("amrita: HTML template library");
		
		data.put("raa", t);
		
		expected = "<a href=\"http://raa.ruby-lang.org/list.rhtml?name=amrita\" >[amrita: HTML template library]</a>";
		
		scenario();
		verify();
	}	
	
	public void testAmritaTypeUseOriginalElement() {
		templateString = "<p>See <a id='a3' amrita:type='use_original_element' href='http://www.ruby-lang.org/'>Ruby homepage</a> for detail</p>";
		
		data = new HashMap<String, Object>();
		
		data.put("a3", new AmritaJProc() {
			public HtmlNode execute(HtmlNode node) {
				node.addChild(new TextNodeImpl(node.getRoot(), node, "(Javanese)"));
				Map<String, String> attr = node.getAttributeMap();
				String href = attr.get("href");
				attr.put("href", href + "ja");
				return node;
			}
		});
		
		expected = "<p>See <a href=\"http://www.ruby-lang.org/ja\" >Ruby homepage(Javanese)</a> for detail</p>";
		
		scenario();
		verify();
	}
	
	public void testAmritaTypeInput() {
		templateString = "<p><input id='i1' amrita:type='input'/></p>";
		
		data = new HashMap<String, Object>();
		
		data.put("i1", "i1val");

		expected = "<p><input value=\"i1val\"/></p>";
		
		scenario();
		verify();
	}
	
	public void testAmritaScript() {
		templateString = "<p><span amrita:script='js'>root.get(\"i1\");</span><span id='i1' amrita:script='js'>i1</span></p>";
		
		data = new HashMap<String, Object>();
		
		data.put("i1", "i1val");

		expected = "<p>i1vali1val</p>";
		
		scenario();
		verify();
	}
	
	public class Root {
		public Child getChild() {
			return new Child();
		}
	}
	
	public class Child {
		public String getHoge() {
			return "hoge";
		}
	}
	
	public void testAmritaScriptAttribute() {
		templateString = "<p><span id='child' hoge='child.getHoge()' amrita:script='js'></span></p>";
		
		data2 = new Root();
		
		expected = "<p><span hoge=\"hoge\"/></p>";
		
		scenario2();
		verify();
	}

	private void scenario() {
		TemplateText tmpl = new TemplateText(templateString);
		StringWriter sw = new StringWriter();
		
		//tmpl.setHandleString("id");
		
		tmpl.expand(sw, data);
		
		result = sw.toString();
	}
	
	private void scenario2() {
		TemplateText tmpl = new TemplateText(templateString);
		StringWriter sw = new StringWriter();
		
		//tmpl.setHandleString("id");
		
		tmpl.expand(sw, data2);
		
		result = sw.toString();
	}
	
	private void verify() {
		assertEquals(expected, result);
	}
}
