/*
 * 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 junit.framework.TestCase;

import org.w3c.dom.Node;

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

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());
	}
}
