package net.firefang.ip2c;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class IP2CountryTest
{
	static long total = 0;
	static long num = 0;
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException
	{
		String line = null;
		try
		{
			String csvFile = "ip-to-country.csv";
			String binFile = "ip-to-country.bin";
			if (true)//(new File(csvFile).lastModified() > new File(binFile).lastModified())
			{
				System.out.println("Building new bin");
				IP2Country.compileCSV(csvFile, binFile);	
			}
			else
			{
				System.out.println("Using existing bin");
			}
			
			IP2Country ip2c = new IP2Country(binFile, IP2Country.MEMORY_MAPPED);
			
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(csvFile)));
			
			int c = 0;
			
			while ((line = reader.readLine()) != null)
			{
				if (line.length() == 0) continue;
				StringTokenizer tok = new StringTokenizer(line, "\",");
				long start = Long.parseLong(tok.nextToken());
				long end = Long.parseLong(tok.nextToken());
				
				String id2c = tok.nextToken();
				String id3c = "";
				String name = "";
				if (tok.hasMoreElements())
				{
					id3c = tok.nextToken();
					if (tok.hasMoreElements())
					{
						// name can containt a comma, which messes things up.
						int i = line.lastIndexOf('\"',line.length() - 2);
						name = line.substring(i + 1, line.length() - 1);
					}
				}
				
				Country expected = new Country(id2c, id3c, name);
				test(ip2c, expected, start);
				if (end - start > 1)
					test(ip2c, expected, start+1);
				if (end < (long)Integer.MAX_VALUE * 2)
					test(ip2c, expected, end);
				if (end - start > 1 && (end-1) < (long)Integer.MAX_VALUE * 2)
					test(ip2c, expected, end-1);
				test(ip2c, expected, (start+end)/2);
				c++;
				if (c % 1000 == 0) System.err.println("Tested " + c + " ranges");
			}	
			
			System.err.println("Tested " + num + " ranges in " + total + " ms");
			System.out.println("test passed, avg = " + (float)total / (float)num);	
		} 
		catch (Error e)
		{
			System.err.println("Error in line : " + line);
			e.printStackTrace(System.out);
		}
		
	}
	
	private static void test(IP2Country ip2c, Country expected, long ip) throws IOException
	{
		String ips = getIPString(ip);
		long now = System.currentTimeMillis();
		Country country = ip2c.getCountry(ips);
		total += System.currentTimeMillis() - now;
		num++;
		
		if (expected == null && country == null) return;
		if (expected == null && country != null) throw new RuntimeException("Expected " + expected + ", got " + country + " ||| " + ip); 
		if (expected != null && country == null) throw new RuntimeException("Expected " + expected + ", got " + country + " ||| " + ip);
		
		if (!(country.equals(expected)))
		{
			throw new RuntimeException("Expected " + expected + ", got " + country + " ||| " + ip);
		}

	}

	private static String getIPString(long i)
	{
		short a1 = (short) ((i & 0xff000000l) >> 24);
		short a2 = (short) ((i & 0x00ff0000l) >> 16);
		short a3 = (short) ((i & 0x0000ff00l) >> 8);
		short a4 = (short) ((i & 0x000000ffl) >> 0);
		
		return a1 + "." + a2 + "." + a3 + "." + a4;
	}

}
