/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * 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 woolpack.test;


import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.w3c.dom.Node;

import woolpack.dom.DomContext;
import woolpack.test.TestUtils;
import woolpack.utils.MapBuilder;

import junit.framework.TestCase;

public class TestUtilsTest extends TestCase {
	
	public void testQuery(){
		assertTrue(TestUtils.equals(
				MapBuilder.get(new HashMap<String,List<String>>())
				.put("name0",Arrays.asList("value00","value01"))
				.put("name1",Arrays.asList("value10","value11"))
				.put("name2",Arrays.asList("value20","value21"))
				.get(), TestUtils.selectQuery("hoge.html?name0=value00&name1=value10&name2=value20&name0=value01&name1=value11&name2=value21")));
	}
	
	public void testSelectForm(){
		final DomContext context = new DomContext();
		TestUtils.getToNodeForm(
				"<TEXTAREA name=\"name0\" >value00</TEXTAREA>" +
				"<INPUT name=\"name1\" value=\"value10\" />" +
				"<SPAN id=\"name2\">value20</SPAN>" +
				"<TEXTAREA name=\"name0\" >value01</TEXTAREA>" +
				"<INPUT name=\"name1\" value=\"value11\" />" +
				"<SPAN id=\"name2\">value21</SPAN>" +
				"<INPUT type=\"radio\" name=\"name3\" value=\"value30\" />" +
				"<INPUT type=\"radio\" name=\"name3\" value=\"value31\" checked=\"true\" />" +
				"<INPUT type=\"checkbox\" name=\"name4\" value=\"value40\" />" +
				"<INPUT type=\"checkbox\" name=\"name4\" value=\"value41\" checked=\"true\" />" +
				"<SELECT name=\"name5\">" +
				"<OPTION value=\"value50\" />label50" +
				"<OPTION value=\"value51\" selected=\"true\" />label51" +
				"</SELECT>" +
				"<BUTTON name=\"name6\" value=\"value61\" />"
		).interpret(context);
		final Map<String,List<String>> map = TestUtils.selectForm(context.getNode());

		assertTrue(TestUtils.equals(
				MapBuilder.get(new HashMap<String,List<String>>())
				.put("name0",Arrays.asList("value00","value01"))
				.put("name1",Arrays.asList("value10","value11"))
				.put("name3",Arrays.asList("value31"))
				.put("name4",Arrays.asList("value41"))
				.put("name5",Arrays.asList("value51"))
				.put("name6",Arrays.asList("value61"))
				.get(), map));
	}
	
	public void testSelectEmbedded(){
		final DomContext context = new DomContext();
		TestUtils.getToNodeForm(
				"<TEXTAREA name=\"name0\" >value00</TEXTAREA>" +
				"<INPUT name=\"name1\" value=\"value10\" />" +
				"<SPAN id=\"name2\">value20</SPAN>" +
				"<TEXTAREA name=\"name0\" >value01</TEXTAREA>" +
				"<INPUT name=\"name1\" value=\"value11\" />" +
				"<SPAN id=\"name2\">value21</SPAN>" +
				"<INPUT type=\"radio\" name=\"name3\" value=\"value30\" />" +
				"<INPUT type=\"radio\" name=\"name3\" value=\"value31\" checked=\"true\" />" +
				"<INPUT type=\"checkbox\" name=\"name4\" value=\"value40\" />" +
				"<INPUT type=\"checkbox\" name=\"name4\" value=\"value41\" checked=\"true\" />" +
				"<SELECT name=\"name5\">" +
				"<OPTION value=\"value50\" />label50" +
				"<OPTION value=\"value51\" selected=\"true\" />label51" +
				"</SELECT>"
		).interpret(context);
		final Map<String,List<String>> map = TestUtils.selectEmbedded(Arrays.asList("id"), context.getNode());

		assertTrue(TestUtils.equals(
				MapBuilder.get(new HashMap<String,List<String>>())
				.put("name2",Arrays.asList("value20","value21"))
				.get(), map));
	}
	
	public void testPrint(){
		final DomContext context = new DomContext();
		TestUtils.getToNodeForm(
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>").interpret(context);
		TestUtils.print(context);
	}
	
	private void scenario(final boolean expected, final String s0, final String s1){
		final DomContext context0 = new DomContext();
		TestUtils.getToNodeForm(s0).interpret(context0);
		
		final DomContext context1 = new DomContext();
		TestUtils.getToNodeForm(s1).interpret(context1);
		
		assertEquals(expected, TestUtils.equals(context0.getNode(), context1.getNode()));
		assertTrue(context0.getNode() != context1.getNode());
	}
	
	public void testDefferentDocument(){
		scenario(true, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>");
	}
	
	public void testAttrOrder(){
		scenario(true, 
				"<!-- hoge -->" + 
				"<TEXTAREA id=\"id0\" name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" id=\"id0\" >value0</TEXTAREA>");
	}
	
	public void testDefferentAttrValue(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name1\" >value0</TEXTAREA>");
	}
	
	public void testDefferentAttrRack(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA >value0</TEXTAREA>");
	}
	
	public void testDefferentOption(){
		scenario(true, 
				"<!-- hoge -->" + 
				"<SELECT name=\"name0\" ><OPTION value=\"value0\" >label0</OPTION></SELECT>",
				"<!-- hoge -->" + 
				"<SELECT name=\"name0\" ><OPTION value=\"value0\" >label0</OPTION></SELECT>");
	}
	
	public void testDefferentChildRack(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<SELECT name=\"name0\" ><OPTION value=\"value0\" >label0</OPTION></SELECT>",
				"<!-- hoge -->" + 
				"<SELECT name=\"name0\" ></SELECT>");
	}
	
	public void testDefferentAttrName(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA namf=\"name0\" >value0</TEXTAREA>");
	}
	
	public void testDefferentText(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value1</TEXTAREA>");
	}
	
	public void testDefferentComment(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>",
				"<!-- piyo -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>");
	}
	
	public void testNull0(){
		final DomContext context = new DomContext();
		TestUtils.getToNodeForm(
				"<!-- hoge -->" + 
				"<TEXTAREA name=\"name0\" >value0</TEXTAREA>").interpret(context);
		
		assertTrue(TestUtils.equals((Node)null, null));
		assertFalse(TestUtils.equals((Node)null, context.getNode()));
		assertFalse(TestUtils.equals(context.getNode(), null));
	}

	public void testDefferentElementName(){
		scenario(false, 
				"<!-- hoge -->" + 
				"<SPAN>hoge</SPAN>",
				"<!-- hoge -->" + 
				"<DIV>hoge</DIV>");
	}

	public void testDefferentNodeType(){
		scenario(false, 
				"<!-- hoge -->" + 
				"hoge",
				"<!-- hoge -->" + 
				"<DIV>hoge</DIV>");
	}
	
	private void checkEquals(final boolean expected, final Object o0, final Object o1){
		assertEquals(expected, TestUtils.equals(o0, o1));
	}
	
	public void testEquals(){
		checkEquals(true, null, null);
		checkEquals(false, 1, null);
		checkEquals(false, null, 1);
		
		checkEquals(true, 1, 1);
		checkEquals(false, 1, 2);
		
		checkEquals(true, Arrays.asList(1, 2), Arrays.asList(1, 2));
		checkEquals(false, Arrays.asList(1, 2), Arrays.asList(2, 1));
		checkEquals(false, Arrays.asList(1, 2), Arrays.asList(1, 3));
		checkEquals(false, Arrays.asList(1, 2), Arrays.asList(1));
		
		checkEquals(true, new HashSet<Integer>(Arrays.asList(1, 2)), Arrays.asList(1, 2));
		checkEquals(true, new HashSet<Integer>(Arrays.asList(1, 2)), Arrays.asList(2, 1));
		checkEquals(false, new HashSet<Integer>(Arrays.asList(1, 2)), Arrays.asList(1, 3));
		checkEquals(false, new HashSet<Integer>(Arrays.asList(1, 2)), Arrays.asList(1));
		
		checkEquals(true, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(2,12).put(1,11).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,13).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(3,12).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).get(), MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get());
		
		checkEquals(true, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).put(2,12).get());
		checkEquals(true, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(2,12).put(1,11).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).put(2,13).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).put(3,12).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).put(2,12).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).get());
		checkEquals(false, MapBuilder.get(new LinkedHashMap<Integer,Integer>()).put(1,11).get(), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).put(2,12).get());
		
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).get(), 1);
		checkEquals(false, 1, MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).get());
		
		checkEquals(false, Arrays.asList(1), 1);
		checkEquals(false, 1, Arrays.asList(1));
		
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).get(), Arrays.asList(1));
		checkEquals(false, Arrays.asList(1), MapBuilder.get(new HashMap<Integer,Integer>()).put(1,11).get());
		
		checkEquals(true, MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get());
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(2,1)).get());
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,3)).get());
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1)).get());

		checkEquals(true, MapBuilder.get(new HashMap<Integer,Object>()).put(1,new HashSet<Integer>(Arrays.asList(1,2))).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,2)).get());
		checkEquals(true, MapBuilder.get(new HashMap<Integer,Object>()).put(1,new HashSet<Integer>(Arrays.asList(1,2))).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(2,1)).get());
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Object>()).put(1,new HashSet<Integer>(Arrays.asList(1,2))).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1,3)).get());
		checkEquals(false, MapBuilder.get(new HashMap<Integer,Object>()).put(1,new HashSet<Integer>(Arrays.asList(1,2))).get(), MapBuilder.get(new HashMap<Integer,Object>()).put(1,Arrays.asList(1)).get());
	}
}
