package net.azib.ipscan.config;

import junit.framework.AssertionFailedError;
import org.junit.Before;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.regex.Pattern;

import static org.junit.Assert.*;

public class LabelsTest {

	@Before
	public void setUp() throws Exception {
		// Labels should initialize themselves on first load
	}
	
	@Test
	public void testReinitialize() {
		Labels.initialize(new Locale("en"));
		Object oldInternalInstance = Labels.getInstance();
		Labels.initialize(new Locale("en"));
		assertTrue(oldInternalInstance == Labels.getInstance());
	}
	
	@Test
	public void testInitialize() {
		Labels.initialize(new Locale("en"));
		Object oldInternalInstance = Labels.getInstance();
		Labels.initialize(new Locale("ee"));
		assertFalse(oldInternalInstance == Labels.getInstance());
	}

	@Test
	public void testSimpleLabel() {
		assertEquals("&Scan", Labels.getLabel("menu.scan"));
	}
	
	@Test
	public void testInexistentLabel() {
		assertEquals("abra-cadabra", Labels.getLabel("abra-cadabra"));
	}

	/**
	 * This test recursively processes all source files and tries
	 * to resolve every label it finds. 
	 */
	@Test
	public void testAllLabels() throws IOException {
		var srcDir = new File(findBaseDir(), "src");
		recurseAndTestLabels(srcDir);
	}
	
	public static File findBaseDir() {
		var url = LabelsTest.class.getClassLoader().getResource("messages.properties");
		var parent = new File(url.getPath());
        while (!new File(parent, "build.gradle").exists())
            parent = parent.getParentFile();
		return parent;
	}

	private void recurseAndTestLabels(File dir) throws IOException {
		String files[] = dir.list();
		for (String s : files) {
			var file = new File(dir, s);
			if (file.isDirectory()) {
				recurseAndTestLabels(file);
			}
			else if (file.getName().endsWith(".java")) {
				findAndTestLabels(file);
			}
		}
	}

	private void findAndTestLabels(File file) throws IOException {
		// TODO: tune these regexps
		final var LABELS_REGEX = Pattern.compile("Label.get{1,60}\"([a-z]\\w+?\\.[a-z][\\w.]+?\\w)\"");
		final var EXCEPTION_REGEX = Pattern.compile("new\\s+?(\\w+?Exception)\\(\"([\\w.]+?\\w)\"");

		var fileReader = new BufferedReader(new FileReader(file));
		var sb = new StringBuilder();
		String fileLine;
		while ((fileLine = fileReader.readLine()) != null) {
			sb.append(fileLine);
		}
		fileReader.close();
		var fileContent = sb.toString();
		
		String key = null;
//		String value = null;
		try {
//			System.out.println(file.getPath());

			var matcher = LABELS_REGEX.matcher(fileContent);
			while (matcher.find()) {
				// try to load the label
				key = matcher.group(1);
//				value = 
				Labels.getLabel(key);
//				System.out.println(key + "=" + value);
			}

			matcher = EXCEPTION_REGEX.matcher(fileContent);
			while (matcher.find()) {
				// try to load the label
				key = "exception." + matcher.group(1) + "." + matcher.group(2);
//				value = 
				Labels.getLabel(key);
//				System.out.println(key + "=" + value);
			}
		}
		catch (MissingResourceException e) {
			throw new AssertionFailedError("Label not found: " + key + ", in file: " + file.getPath());
		}
	}
}
