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