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

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;

import junit.framework.TestCase;
import woolpack.locale.BranchByLocaleValidator;
import woolpack.test.TestUtils;
import woolpack.utils.SwitchBuilder;
import woolpack.validator.BranchByIdValidator;
import woolpack.validator.BranchByNameIfExistsValidator;
import woolpack.validator.BranchByNameValidator;
import woolpack.validator.CountValidator;
import woolpack.validator.DefaultValueValidator;
import woolpack.validator.DelegationValidator;
import woolpack.validator.DumpValidator;
import woolpack.validator.EqualsValidator;
import woolpack.validator.FormatValidator;
import woolpack.validator.IfNotValidator;
import woolpack.validator.IfValidator;
import woolpack.validator.MaxLengthValidator;
import woolpack.validator.MaxValidator;
import woolpack.validator.MessageValidator;
import woolpack.validator.MinLengthValidator;
import woolpack.validator.MinValidator;
import woolpack.validator.NotValidator;
import woolpack.validator.ParseValidator;
import woolpack.validator.RegExpIdValidator;
import woolpack.validator.RegExpValidator;
import woolpack.validator.RetainNamesValidator;
import woolpack.validator.SerialValidator;
import woolpack.validator.TmpIndexValidator;
import woolpack.validator.TmpKeyValidator;
import woolpack.validator.ValidNamesValidator;
import woolpack.validator.ValidValuesValidator;
import woolpack.validator.ValidatorConstants;
import woolpack.validator.ValidatorExpression;
import woolpack.validator.ValueLoopValidator;
import woolpack.visitor.Visitor;

public class MessageConstantsTest extends TestCase {
	
	private void scenario(final Object expression, final Object expected){
		final Visitor visitor = new Visitor();
		visitor.setMap(MessageConstants.MAP);
		visitor.setContext(new ArrayList<String>());
		visitor.visit(expression);
		assertTrue(TestUtils.equals(expected, visitor.getContext()));
	}
	
	private void scenarioEmpty(final ValidatorExpression expression){
		scenario(expression, Collections.EMPTY_LIST);
	}

	public void testBranchByIdValidator(){
		scenario(new BranchByIdValidator(new SwitchBuilder<String,ValidatorExpression>()
				.put("id0", new MessageValidator("message0"))
				.put("id1", new MessageValidator("message1"))
				.get(new MessageValidator("message2"))),
				Arrays.asList("message0", "message1", "message2"));
	}

	public void testBranchByNameIfExistsValidator(){
		scenario(new BranchByNameIfExistsValidator(new SwitchBuilder<String,ValidatorExpression>()
				.put("id0", new MessageValidator("message0"))
				.put("id1", new MessageValidator("message1"))
				.get(new MessageValidator("message2"))),
				Arrays.asList("message0", "message1", "message2"));
	}

	public void testBranchByNameValidator(){
		scenario(new BranchByNameValidator(new SwitchBuilder<String,ValidatorExpression>()
				.put("id0", new MessageValidator("message0"))
				.put("id1", new MessageValidator("message1"))
				.get(new MessageValidator("message2"))),
				Arrays.asList("message0", "message1", "message2"));
	}

	public void testCountValidator(){
		scenario(new CountValidator(new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testDefaultValueValidator1(){
		scenarioEmpty(new DefaultValueValidator("message0"));
	}

	public void testDefaultValueValidator2(){
		scenario(new DefaultValueValidator(new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testDelegationValidator(){
		scenario(new DelegationValidator(new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testDumpValidator(){
		scenario(new DumpValidator(new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testEqualsValidator1(){
		scenarioEmpty(new EqualsValidator("message0"));
	}

	public void testEqualsValidator2(){
		scenario(new EqualsValidator(new MessageValidator("message0")), Arrays.asList("message0"));
	}

	public void testFormatValidator(){
		scenarioEmpty(new FormatValidator(new DecimalFormat()));
	}

	public void testIfNotValidator(){
		scenario(new IfNotValidator(new MessageValidator("message0"), new MessageValidator("message1")),
				new HashSet<String>(Arrays.asList("message0", "message1")));
	}

	public void testIfValidator(){
		scenario(new IfValidator(new MessageValidator("message0"), new MessageValidator("message1"), new MessageValidator("message2")),
				Collections.unmodifiableCollection(Arrays.asList("message0", "message1", "message2")));
	}

	public void testMaxLengthValidator(){
		scenarioEmpty(new MaxLengthValidator(1));
	}

	public void testMaxValidator(){
		scenarioEmpty(new MaxValidator(1));
	}

	public void testMessageValidator(){
		scenario(new MessageValidator("message0"), Arrays.asList("message0"));
	}

	public void testMinLengthValidator(){
		scenarioEmpty(new MinLengthValidator(1));
	}

	public void testMinValidator(){
		scenarioEmpty(new MinValidator(1));
	}

	public void testNotValidator(){
		scenario(new NotValidator(new MessageValidator("message0")), Arrays.asList("message0"));
	}

	public void testParseValidator(){
		scenarioEmpty(new ParseValidator(new DecimalFormat()));
	}

	public void testRegExpIdValidator(){
		scenarioEmpty(new RegExpIdValidator(".*"));
	}

	public void testRegExpValidator(){
		scenarioEmpty(new RegExpValidator(".*"));
	}

	public void testRetainNamesValidator(){
		scenarioEmpty(new RetainNamesValidator(Arrays.asList("a")));
	}

	public void testSerialValidator(){
		scenario(new SerialValidator(new MessageValidator("message0"), new MessageValidator("message1")),
				Arrays.asList("message0", "message1"));
	}

	public void testTmpIndexValidator(){
		scenario(new TmpIndexValidator(1, new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testTmpKeyValidator(){
		scenario(new TmpKeyValidator("key0", new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testTrueValidator(){
		scenarioEmpty(ValidatorConstants.TRUE);
	}

	public void testFalseValidator(){
		scenarioEmpty(ValidatorConstants.FALSE);
	}

	public void testRequiredValidator(){
		scenarioEmpty(ValidatorConstants.REQUIRED);
	}

	public void testValidNamesValidator(){
		scenarioEmpty(new ValidNamesValidator(Arrays.asList("message0")));
	}

	public void testValidValuesValidator(){
		scenarioEmpty(new ValidValuesValidator(Arrays.asList("message0")));
	}

	public void testValueLoopValidator(){
		scenario(new ValueLoopValidator(new MessageValidator("message0")),
				Arrays.asList("message0"));
	}

	public void testBranchByLocaleValidator(){
		scenario(new BranchByLocaleValidator(
				new SwitchBuilder<Locale,ValidatorExpression>()
				.put(Locale.JAPANESE, new MessageValidator("message0"))
				.put(Locale.ENGLISH, new MessageValidator("message1"))
				.get(new MessageValidator("message2")), new ThreadLocal<Locale>()),
				Arrays.asList("message0", "message1", "message2"));
	}
}
