/*
 * Copyright (C) 2010.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

package uk.me.parabola.imgfmt.app.srt;

import java.text.Collator;

import uk.me.parabola.mkgmap.srt.SrtTextReader;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class SortTest {
	private Sort sort;
	private Collator collator;

	@Before
	public void setUp() throws Exception {
		sort = SrtTextReader.sortForCodepage(1252);

		collator = sort.getCollator();
		collator.setStrength(Collator.TERTIARY);
	}

	@Test
	public void testSame() {
		String s = "aAbâ";
		SortKey<Object> k1 = sort.createSortKey(null, s);
		SortKey<Object> k2 = sort.createSortKey(null, s);

		assertEquals(0, k1.compareTo(k2));
	}

	@Test
	public void testDifferentLengths() {
		SortKey<Object> k1 = sort.createSortKey(null, "aabbbb");
		SortKey<Object> k2 = sort.createSortKey(null, "aab");

		assertEquals(1, k1.compareTo(k2));
		assertEquals(-1, k2.compareTo(k1));
	}

	@Test
	public void testPrimaryDifference() {
		checkOrdered("AAA", "AAB");
	}

	@Test
	public void testSecondaryDifferences() {
		checkOrdered("AAA", "AÂA");
	}

	@Test
	public void testTertiaryDifferences() {
		checkOrdered("AAa", "AAA");
	}

	@Test
	public void testPrimaryOverridesSecondary() {
		checkOrdered("AAAA", "ÂAAA");
		checkOrdered("ÂAAA", "AAAB");
	}

	@Test
	public void testSecondaryOverridesTertiary() {
		checkOrdered("aaa", "Aaa");
		checkOrdered("Aaa", "aâa");
		checkOrdered("Aaa", "aÂa");
	}

	@Test
	public void testSecondarySort() {
		checkOrdered(1, 24);
	}

	@Test
	public void testLengths() {
		assertEquals(-1, keyCompare("-Û", "-ü:X"));
		assertEquals(-1, keyCompare("-ü:X", "-Û$"));
		assertEquals(-1, keyCompare("–", "–X"));
		assertEquals(1, keyCompare("–TÛ‡²", "–"));
	}

	/**
	 * Test for a bad character in the input.
	 * Probably want the character to be replaced by a question mark rather
	 * than give an error.
	 * Strings with bad characters should not compare equal to other strings
	 * or throw exceptions.
	 */
	@Test
	public void testBadCharacter() {
		String s = "a\u063ab";
		SortKey<Object> k1 = sort.createSortKey(null, s);
		SortKey<Object> k2 = sort.createSortKey(null, "aa");

		assertTrue(k1.compareTo(k2) != 0);

		assertTrue(k2.compareTo(k1) != 0);

		// not equal to an empty string.
		k2 = sort.createSortKey(null, "");
		assertTrue(k1.compareTo(k2) != 0);

		// character is replaced with '?'
		k2 = sort.createSortKey(null, "a?b");
		assertEquals(0, k1.compareTo(k2));
	}

	@Test
	public void testTertiaryPlusExpansion() {
		assertEquals(-1, keyCompare("æ", "ªe"));
		assertEquals(-1, keyCompare("`æ", "`ªe"));
	}

	/**
	 * Make the internal initial buffer overflow so it has to be reallocated.
	 */
	@Test
	public void testKeyOverflow() {
		assertEquals(1, keyCompare("™™™™™", "AA"));
	}

	@Test
	public void testExpanded() {
		assertEquals(-1, keyCompare("æ", "Ae"));
		assertEquals(-1, keyCompare("æ", "AE"));
		assertEquals(-1, keyCompare("æ", "aE"));
		assertEquals(1, keyCompare("AE", "aE"));

		assertEquals(-1, keyCompare("–TMO", "–uÊÑÇ"));
		assertEquals(-1, keyCompare("–™O", "–uÊÑÇ"));
	}

	@Test
	public void testExpand2() {
		assertEquals(1, keyCompare("™ð", "tMÐ"));
	}

	@Test
	public void testIgnorable() {
		assertEquals(-1, keyCompare("\u007fæ", "Ae"));
	}

	@Test
	public void testIgnorableCharacters() {
		assertEquals(0, keyCompare("aaa", "a\u0008aa"));

		assertEquals(-1, keyCompare("\u007f", "(T"));
	}

	@Test
	public void testSecondaryIgnorable() {
		assertEquals(1, keyCompare("\u0001A", "A\u0008"));
	}

	@Test
	public void testSpaces() {
		assertEquals(1, keyCompare("øþõ Ñ", "õþO"));
	}

	private int keyCompare(String s1, String s2) {
		SortKey<Object> k1 = sort.createSortKey(null, s1);
		SortKey<Object> k2 = sort.createSortKey(null, s2);
		System.out.println("K1: " + k1);
		System.out.println("K2: " + k2);

		return k1.compareTo(k2);
	}

	private void checkOrdered(int i1, int i2) {
		String s = "aaa";
		SortKey<Object> k1 = sort.createSortKey(null, s, i1);
		SortKey<Object> k2 = sort.createSortKey(null, s, i2);
		assertEquals(1, k2.compareTo(k1));
	}

	/**
	 * Check and assert that the second string is greater than the first.
	 * @param s First string.
	 * @param s1 Second string.
	 */
	private void checkOrdered(String s, String s1) {
		SortKey<Object> k1 = sort.createSortKey(null, s);
		SortKey<Object> k2 = sort.createSortKey(null, s1);

		assertEquals(1, k2.compareTo(k1));
		assertEquals(-1, k1.compareTo(k2));
		assertEquals(-1, collator.compare(s, s1));
		assertEquals(1, collator.compare(s1, s));
	}
}
