
package org.ajwcc.pduUtils.test;

import java.lang.reflect.*;
import java.util.*;
import org.ajwcc.pduUtils.gsm3040.*;
import org.smslib.*;
import org.smslib.Message.*;

public class MessageGeneratorTester
{
	public static void main(String[] args) throws Exception
	{
		String smscNo = "";
		int testCount = 0;
		int passCount = 0;
		// load a file for testing
		TestFileReader tfr = new TestFileReader();
		tfr.setSkipBlanksAndComment(false);
		tfr.init("java/org/ajwcc/pduUtils/testData/testMessages.txt");
		String currentLine;
		Message message = null;
		ArrayList<String> expectedPdus = new ArrayList<String>();
		main: while ((currentLine = tfr.next()) != null)
		{
			if (currentLine.trim().equals(""))
			{
				System.out.println(currentLine);
			}
			else if (currentLine.trim().startsWith("#"))
			{
				System.out.println(currentLine);
			}
			else
			{
				String[] data = new String[2];
				int colon = currentLine.indexOf(':');
				data[0] = currentLine.substring(0, colon);
				data[1] = currentLine.substring(colon + 1);
				if (data[0].equals("messageType"))
				{
					message = (Message) Class.forName(data[1]).newInstance();
					testCount++;
				}
				else if (data[0].equals("messageEnd"))
				{
					if (message != null)
					{
						// display pdus
						List<String> pdus = ((OutboundMessage) message).getPdus(smscNo, 123);
						StringBuffer sb = new StringBuffer();
						for (String pduString : pdus)
						{
							Pdu pdu = new PduParser().parsePdu(pduString);
							System.out.println(pdu);
							if (message instanceof OutboundBinaryMessage)
							{
								sb.append(PduUtils.bytesToPdu(pdu.getUserDataAsBytes()));
							}
							else if (message instanceof OutboundMessage)
							{
								sb.append(pdu.getDecodedText());
							}
						}
						System.out.println("EXPECTED PDUs   : " + expectedPdus.size());
						System.out.println("GENERATED PDUs  : " + pdus.size());
						if (message instanceof OutboundBinaryMessage)
						{
							OutboundBinaryMessage bin = (OutboundBinaryMessage) message;
							System.out.println("EXPECTED BYTES : " + PduUtils.bytesToPdu(bin.getDataBytes()));
							System.out.println("GENERATED BYTES: " + sb.toString());
							boolean match = sb.toString().equals(PduUtils.bytesToPdu(bin.getDataBytes()));
							System.out.println("MATCH: " + match);
							if (match) passCount++;
						}
						else if (message instanceof OutboundMessage)
						{
							System.out.println("EXPECTED TEXT : " + message.getText());
							System.out.println("GENERATED TEXT: " + sb.toString());
							boolean match = sb.toString().equals(message.getText());
							System.out.println("MATCH: " + match);
							if (match) passCount++;
						}
					}
					System.out.println();
					expectedPdus.clear();
					message = null;
					smscNo = "";
				}
				else if (data[0].equals("encoding"))
				{
					if (data[1].equals("7"))
					{
						((OutboundMessage) message).setEncoding(MessageEncodings.ENC7BIT);
					}
					else if (data[1].equals("8"))
					{
						((OutboundMessage) message).setEncoding(MessageEncodings.ENC8BIT);
					}
					else if (data[1].equals("ucs2"))
					{
						((OutboundMessage) message).setEncoding(MessageEncodings.ENCUCS2);
					}
				}
				else if (data[0].equals("expectedPdu"))
				{
					expectedPdus.add(data[1]);
				}
				else if (data[0].equals("smscNumber"))
				{
					smscNo = data[1];
				}
				else if (data[0].equals("dataBytes"))
				{
					((OutboundBinaryMessage) message).setDataBytes(PduUtils.pduToBytes(data[1]));
				}
				else
				{
					// reflection
					// retrieve method getter for data[0]
					// get return type
					Class<?> currentClass = message.getClass();
					while (currentClass != Object.class)
					{
						try
						{
							Method getter = message.getClass().getMethod("get" + Character.toUpperCase(data[0].charAt(0)) + data[0].substring(1));
							Class<?> returnType = getter.getReturnType();
							// retrieve setter for data[0]
							// invoke with the data[1] based on type
							Method setter = currentClass.getDeclaredMethod("set" + Character.toUpperCase(data[0].charAt(0)) + data[0].substring(1), returnType);
							setter.setAccessible(true);
							setter.invoke(message, convertStringToArgument(returnType, data[1]));
							continue main;
						}
						catch (Exception e)
						{
							currentClass = currentClass.getSuperclass();
						}
					}
				}
			}
		}
		tfr.close();
		System.out.println();
		System.out.println("Total Tests: " + testCount);
		System.out.println("Passed: " + passCount);
	}

	public static Object convertStringToArgument(Class<?> c, String data)
	{
		if ((c == Boolean.class) || (c == Boolean.TYPE))
		{
			return Boolean.valueOf(data);
		}
		else if ((c == Integer.class) || (c == Integer.TYPE))
		{
			return Integer.valueOf(data);
		}
		else if ((c == Long.class) || (c == Long.TYPE))
		{
			return Long.valueOf(data);
		}
		else if ((c == Integer.class) || (c == Integer.TYPE))
		{
			return Integer.valueOf(data);
		}
		else if ((c == Short.class) || (c == Short.TYPE))
		{
			return Short.valueOf(data);
		}
		else if (c == String.class) { return data; }
		return null;
	}
}
