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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import junit.framework.TestCase;
import woolpack.dom.Count;
import woolpack.dom.DomConstants;
import woolpack.dom.DomContext;
import woolpack.dom.DomExpression;
import woolpack.dom.XmlToNode;
import woolpack.test.TestUtils;
import woolpack.utils.IOExceptionReaderFactory;

public class LocaleIdTest extends TestCase {

	public void testConstructor() {
		try {
			new LocaleId(null, new ThreadLocal<Locale>());
			fail();
		} catch (final NullPointerException expected) {
		}
		try {
			new LocaleId(DomConstants.NULL, null);
			fail();
		} catch (final NullPointerException expected) {
		}
	}

	public void testSearch() {
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final List<String> result = new ArrayList<String>();
		final Count counter = new Count(new DomExpression() {
			public void interpret(final DomContext context) {
				result.add(context.getId());
			}
		});
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();
		context.setId("id0");

		final Locale defaultLocale = Locale.getDefault();
		try {
			Locale.setDefault(new Locale("ja", "JP", "POSIX"));

			result.clear();
			threadLocal.set(new Locale("en", "US", "WIN"));
			try {
				expression.interpret(context);
				fail();
			} catch (final IllegalStateException expected) {
			}
			assertEquals(7, counter.getCount());
			assertTrue(TestUtils.equals(Arrays.asList("id0_en_US_WIN",
					"id0_en_US", "id0_en", "id0_ja_JP_POSIX", "id0_ja_JP",
					"id0_ja", "id0"), result));

			result.clear();
			threadLocal.set(null);
			try {
				expression.interpret(context);
				fail();
			} catch (final IllegalStateException expected) {
			}
			assertEquals(11, counter.getCount());
			assertTrue(TestUtils.equals(Arrays.asList("id0_ja_JP_POSIX",
					"id0_ja_JP", "id0_ja", "id0"), result));
		} finally {
			Locale.setDefault(defaultLocale);
		}

	}

	public void testNormal() {
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(TestUtils.getToNodeBody("test"));
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		expression.interpret(context);
		assertEquals(1, counter.getCount());
		assertTrue(TestUtils.equalsBody(context, "test"));
	}

	public void testIOException() {
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(new XmlToNode(
				new IOExceptionReaderFactory()));
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try {
			expression.interpret(context);
			fail();
		} catch (final IllegalStateException expected) {
			assertTrue(expected.getCause() instanceof IOException);
		}
	}

	public void testException() {
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(new DomExpression() {
			public void interpret(final DomContext context) {
				throw new RuntimeException();
			}
		});
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try {
			expression.interpret(context);
			fail();
		} catch (final RuntimeException expected) {
			assertNull(expected.getCause());
		}
	}

	public void testNull() {
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(DomConstants.NULL);
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try {
			expression.interpret(context);
			fail();
		} catch (final IllegalStateException expected) {
			assertNull(expected.getCause());
		}
	}
}
