/*
 * 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.validator;

import java.util.Arrays;
import java.util.Map;
import java.util.regex.Pattern;

import junit.framework.TestCase;
import woolpack.convert.ConvertUtils;
import woolpack.fn.Fn;
import woolpack.fn.FnUtils;
import woolpack.fn.ThrowFn;
import woolpack.utils.Utils;

public class ValidatorUtilsTest extends TestCase {
	
	public void testValue() {
		final ValidatorContext context = new ValidatorContext();
		context.setInputMap(Utils
				.map("k", Arrays.asList((Object) "a", "b")));
		context.setKey("k");
		assertEquals("a", ValidatorUtils.VALUE.exec(context));
	}
	
	public void testMap() {
		final ValidatorContext context = new ValidatorContext();
		context.setInputMap(Utils
				.map("k", Arrays.asList((Object) "a", "b")));
		assertEquals(context.getInputMap(), ValidatorUtils.MAP.exec(context));
	}

	public void testValues() {
		final ValidatorContext context = new ValidatorContext();
		context.setInputMap(Utils
				.map("k", Arrays.asList((Object) "a", "b")));
		context.setKey("k");
		assertEquals(Arrays.asList("a", "b"), ValidatorUtils.VALUES.exec(context));
	}

	public void testConvertNormal() {
		assertEquals(Utils
				.map("key0", Arrays.asList("value00", "value01"))
				.map("key1", Arrays.asList("value10", "value11", "value12")),
				ValidatorUtils.convert(Utils
						.map("key0", new String[] { "value00", "value01" })
						.map("key1", new String[] { "value10", "value11", "value12" })));
	}

	public void testConvertKeyClassCast() {
		final Map<Integer, String[]> base = Utils
			.map(Integer.valueOf(1), new String[] { "value00", "value01" });
		try {
			ValidatorUtils.convert(base);
			fail();
		} catch (final ClassCastException expected) {
		}
	}

	public void testConvertValue() {
		final Fn<ValidatorContext, Boolean> fn =
			ValidatorUtils.convertValue(FnUtils.join(
					ConvertUtils.TO_STRING,
					ConvertUtils.convertRegExp(Pattern.compile("(.+)"), "[$1]")
			));
		final ValidatorContext context = new ValidatorContext();
		context.setKey("key0");
		context.setInputMap(Utils.map("key0", Arrays.asList((Object)"a")));
		assertTrue(fn.exec(context));
		assertEquals(
				Utils.map("key0", Arrays.asList((Object)"[a]")),
				context.getInputMap());
	}

	public void testLocalIndex() {
		final Fn<ValidatorContext, Boolean> expression = ValidatorUtils.localIndex(1,
				ValidatorUtils.convertValue(FnUtils.join(
						ConvertUtils.TO_STRING,
						ConvertUtils.convertRegExp(Pattern.compile("(.+)"), "[$1]")
				)));
		final ValidatorContext context = new ValidatorContext();
		context.setInputMap(Utils
				.map("k", Arrays.asList((Object) "a", "b")));
		context.setKey("k");
		assertTrue(expression.exec(context));
		assertEquals(0, context.getIndex());
		assertEquals(
				Utils.map("k", Arrays.asList((Object) "a", "[b]")),
				context.getInputMap());
	}

	public void testLocalIndexException() {
		final Fn<ValidatorContext, Boolean> expression = ValidatorUtils.localIndex(1,
				new ThrowFn<ValidatorContext, Boolean>(new IllegalStateException()));
		final ValidatorContext context = new ValidatorContext();
		try {
			expression.exec(context);
			fail();
		} catch(final IllegalStateException e) {
		}
		assertEquals(0, context.getIndex());
	}
	
	public void testLocalKey() {
		final Fn<ValidatorContext, Boolean> expression = ValidatorUtils.localKey("k",
				ValidatorUtils.convertValue(FnUtils.join(
						ConvertUtils.TO_STRING,
						ConvertUtils.convertRegExp(Pattern.compile("(.+)"), "[$1]")
				)));
		final ValidatorContext context = new ValidatorContext();
		context.setInputMap(Utils
				.map("k", Arrays.asList((Object) "a", "b")));
		assertTrue(expression.exec(context));
		assertEquals(
				Utils.map("k", Arrays.asList((Object) "[a]", "b")),
				context.getInputMap());
	}
	
	public void testLocalKeyException() {
		final Fn<ValidatorContext, Boolean> expression = ValidatorUtils.localKey("k",
				new ThrowFn<ValidatorContext, Boolean>(new IllegalStateException()));
		final ValidatorContext context = new ValidatorContext();
		context.setKey("h");
		try {
			expression.exec(context);
			fail();
		} catch(final IllegalStateException e) {
		}
		assertEquals("h", context.getKey());
	}

	public void testMessage() {
		final Fn<ValidatorContext, Boolean> expression = ValidatorUtils.message("message0");
		final SimpleMessageCollector collector = new SimpleMessageCollector();
		final ValidatorContext context = new ValidatorContext();
		context.setCollectable(collector);

		context.setKey("key0");
		assertFalse(expression.exec(context));
		assertEquals(1, collector.getList().size());
		assertEquals("message0", collector.getList().get(0));
	}
}
