/*
 * 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.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import junit.framework.TestCase;
import woolpack.locale.BranchByLocaleValidator;
import woolpack.text.DelegateDateFormat;
import woolpack.text.DelegateNumberFormat;
import woolpack.text.LimitedValueFormat;
import woolpack.text.RegExpFormat;
import woolpack.text.ToCharacterFormat;
import woolpack.text.ToStringFormat;
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 JsConstantsTest extends TestCase {

	private void scenario(final Object expression, final String expected) {
		final Visitor visitor = new Visitor();
		visitor.setMap(JsConstants.MAP);
		visitor.setContext(new StringBuilder());
		visitor.visit(expression);
		assertEquals(expected, visitor.getContext().toString());
	}

	public void testBranchByIdValidator1() {
		scenario(new BranchByIdValidator(
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get(
						new MessageValidator("message2"))),
				"new BranchByIdValidator({"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByIdValidator2() {
		scenario(new BranchByIdValidator(
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get()),
				"new BranchByIdValidator({"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByNameIfExistsValidator1() {
		scenario(new BranchByNameIfExistsValidator(
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get(
						new MessageValidator("message2"))),
				"new BranchByNameIfExistsValidator(new AndValidatorIterable(),{"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByNameIfExistsValidator2() {
		scenario(new BranchByNameIfExistsValidator(ValidatorConstants.OR,
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get()),
				"new BranchByNameIfExistsValidator(new OrValidatorIterable(),{"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByNameValidator1() {
		scenario(new BranchByNameValidator(
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get(
						new MessageValidator("message2"))),
				"new BranchByNameValidator(new AndValidatorIterable(),{"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByNameValidator2() {
		scenario(new BranchByNameValidator(ValidatorConstants.OR,
				new SwitchBuilder<String, ValidatorExpression>().put("id0",
						new MessageValidator("message0")).put("id1",
						new MessageValidator("message1")).get()),
				"new BranchByNameValidator(new OrValidatorIterable(),{"
						+ "\"id0\":new MessageValidator(\"message0\"),"
						+ "\"id1\":new MessageValidator(\"message1\")})");
	}

	public void testCountValidator() {
		scenario(new CountValidator(new MessageValidator("message0")),
				"new MessageValidator(\"message0\")");
	}

	public void testDefaultValueValidator1() {
		scenario(new DefaultValueValidator("message0"),
				"new DefaultValueValidator(\"message0\")");
	}

	public void testDefaultValueValidator2() {
		scenario(new DefaultValueValidator(new MessageValidator("message0")),
				"new DefaultValueValidator(new MessageValidator(\"message0\"))");
	}

	public void testDelegationValidator() {
		scenario(new DelegationValidator(new MessageValidator("message0")),
				"new DelegationValidator(new MessageValidator(\"message0\"))");
	}

	public void testDumpValidator() {
		scenario(new DumpValidator(new MessageValidator("message0")),
				"new MessageValidator(\"message0\")");
	}

	public void testEqualsValidator1() {
		scenario(new EqualsValidator("message0"),
				"new EqualsValidator(\"message0\")");
	}

	public void testEqualsValidator2() {
		scenario(new EqualsValidator(new MessageValidator("message0")),
				"new EqualsValidator(new MessageValidator(\"message0\"))");
	}

	public void testFormatValidator() {
		scenario(new FormatValidator(new DecimalFormat()),
				"new FormatValidator(new DecimalFormat())");
	}

	public void testFormatValidator2() {
		scenario(new FormatValidator(new DelegateNumberFormat(
				new DecimalFormat())),
				"new FormatValidator(new DecimalFormat())");
	}

	public void testIfNotValidator() {
		scenario(
				new IfNotValidator(new MessageValidator("message0"),
						new MessageValidator("message1")),
				"new IfNotValidator(new MessageValidator(\"message0\"),new MessageValidator(\"message1\"))");
		// new IfValidator(new NotValidator(new MessageValidator(\"message0\")),
		// new MessageValidator(\"message1\"), new TrueValidator())
	}

	public void testIfValidator() {
		scenario(
				new IfValidator(new MessageValidator("message0"),
						new MessageValidator("message1"), new MessageValidator(
								"message2")),
				"new IfValidator(new MessageValidator(\"message0\"),new MessageValidator(\"message1\"),new MessageValidator(\"message2\"))");
	}

	public void testMaxLengthValidator() {
		scenario(new MaxLengthValidator(1), "new MaxLengthValidator(1)");
	}

	public void testMaxValidator() {
		scenario(new MaxValidator(1), "new MaxValidator(1)");
	}

	public void testMessageValidator() {
		scenario(new MessageValidator("message0"),
				"new MessageValidator(\"message0\")");
	}

	public void testMinLengthValidator() {
		scenario(new MinLengthValidator(1), "new MinLengthValidator(1)");
	}

	public void testMinValidator() {
		scenario(new MinValidator(1), "new MinValidator(1)");
	}

	public void testNotValidator() {
		scenario(new NotValidator(new MessageValidator("message0")),
				"new NotValidator(new MessageValidator(\"message0\"))");
	}

	public void testParseValidator() {
		scenario(new ParseValidator(new DecimalFormat()),
				"new ParseValidator(new DecimalFormat())");
	}

	public void testRegExpIdValidator() {
		scenario(new RegExpIdValidator(".*"), "new RegExpIdValidator(\".*\")");
	}

	public void testRegExpValidator() {
		scenario(new RegExpValidator(".*"), "new RegExpValidator(\".*\")");
	}

	public void testRetainNamesValidator() {
		scenario(
				new RetainNamesValidator(Arrays.asList("message0", "message1")),
				"new RetainNamesValidator([\"message0\",\"message1\"])");
	}

	public void testSerialValidator() {
		scenario(
				new SerialValidator(new MessageValidator("message0"),
						new MessageValidator("message1")),
				"new SerialValidator(new AndAndValidatorIterable(),[new MessageValidator(\"message0\"),new MessageValidator(\"message1\")])");
	}

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

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

	public void testTrueValidator() {
		scenario(ValidatorConstants.TRUE, "new TrueValidator()");
	}

	public void testFalseValidator() {
		scenario(ValidatorConstants.FALSE, "new FalseValidator()");
	}

	public void testRequiredValidator() {
		scenario(ValidatorConstants.REQUIRED, "new RequiredValidator()");
	}

	public void testOrValidatorIterable() {
		scenario(ValidatorConstants.OR, "new OrValidatorIterable()");
	}

	public void testOrOrValidatorIterable() {
		scenario(ValidatorConstants.OROR, "new OrOrValidatorIterable()");
	}

	public void testAndValidatorIterable() {
		scenario(ValidatorConstants.AND, "new AndValidatorIterable()");
	}

	public void testAndAndValidatorIterable() {
		scenario(ValidatorConstants.ANDAND, "new AndAndValidatorIterable()");
	}

	public void testEqValidatorIterable() {
		scenario(ValidatorConstants.EQ, "new EqValidatorIterable()");
	}

	public void testEqEqValidatorIterable() {
		scenario(ValidatorConstants.EQEQ, "new EqEqValidatorIterable()");
	}

	public void testValidNamesValidator() {
		scenario(new ValidNamesValidator(Arrays.asList("message0")),
				"new ValidNamesValidator([\"message0\"])");
	}

	public void testValidValuesValidator() {
		scenario(new ValidValuesValidator(Arrays.asList("message0")),
				"new ValidValuesValidator([\"message0\"])");
	}

	public void testValueLoopValidator() {
		scenario(
				new ValueLoopValidator(new MessageValidator("message0")),
				"new ValueLoopValidator(new AndValidatorIterable(),new MessageValidator(\"message0\"))");
	}

	public void testBranchByLocaleValidator1() {
		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>()), "new BranchByLocaleValidator({"
				+ "\"ja\":new MessageValidator(\"message0\"),"
				+ "\"en\":new MessageValidator(\"message1\")})");
	}

	public void testBranchByLocaleValidator2() {
		scenario(
				new BranchByLocaleValidator(
						new SwitchBuilder<Locale, ValidatorExpression>().put(
								Locale.JAPANESE,
								new MessageValidator("message0")).put(
								Locale.ENGLISH,
								new MessageValidator("message1")).get(),
						new ThreadLocal<Locale>()),
				"new BranchByLocaleValidator({"
						+ "\"ja\":new MessageValidator(\"message0\"),"
						+ "\"en\":new MessageValidator(\"message1\")})");
	}

	public void testLimitedValueFormat() {
		final Map<String, String> m0 = new HashMap<String, String>();
		m0.put("key0", "value0");
		m0.put("key1", "value1");
		m0.put("key2", "value2");
		scenario(
				new LimitedValueFormat(m0, "defaultParsedValue",
						"defaultFormattedValue"),
				"new LimitedValueFormat("
						+ "{\"key1\":\"value1\",\"key0\":\"value0\",\"key2\":\"value2\"},"
						+ "\"defaultParsedValue\","
						+ "\"defaultFormattedValue\")");
	}

	public void testDelegateDateFormat() {
		scenario(new DelegateDateFormat(new SimpleDateFormat("yyyyMMddHH")),
				"new SimpleDateFormat(\"yyyyMMddHH\")");
	}

	public void testDateFormat() {
		scenario(new SimpleDateFormat("yyyyMMddHH"),
				"new SimpleDateFormat(\"yyyyMMddHH\")");
	}

	public void testRegExpFormat() {
		scenario(new RegExpFormat(".*", "$1"),
				"new RegExpFormat(\".*\",\"$1\")");
	}

	public void testToCharacterFormat() {
		scenario(new ToCharacterFormat(), "new ToCharacterFormat()");
	}

	public void testToStringFormat() {
		scenario(new ToStringFormat(), "new ToStringFormat()");
	}
}
