package com.n2bb.web.util;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletResponse;

/**
 * @author venkataprasath
 * 
 */
public class ReportWriter extends ReportUtil {
	
	public ReportWriter(HttpServletResponse response, String outputType,
				String headerName, String[][] filteredBy, String sortedBy,
				String[] columnDisplayNames, String[] columnNames,
				String[] parameters, Collection records) {			
			try {
				this.out = response.getWriter();
			} catch (IOException e) {
				n2bbLog.error("", e);
			}
			this.response = response;
			this.outputType = outputType;
			this.headerName = headerName;
			this.filteredBy = filteredBy;
			this.sortedBy = sortedBy;
			this.columnDisplayNames = columnDisplayNames;
			this.columnNames = columnNames;
			this.records = records;
			this.parameters = parameters;			
		}

		public static void generateReport(HttpServletResponse response,
				String outputType, String headerName, String filteredBy[][],
				String sortedBy, String columnDisplayNames[], String columnNames[],
				String[] parameters, Collection records) {			
			ReportWriter reportWriter = new ReportWriter(response,
					outputType, headerName, filteredBy, sortedBy,
					columnDisplayNames, columnNames, parameters, records);
			reportWriter.generate();			
		}

		/**
		 * Gets the value of a record's column via reflection, using the method
		 * "record.getColumnName()". Override to change the way a column value is
		 * extracted.
		 */
		protected Object getColumnValue(Object record, String columnName,
				Object[] arguments) throws NoSuchMethodException,
				IllegalAccessException, InvocationTargetException {
			Class types[] = null;			
			recordClass = record.getClass();
			String methodName = "get" + columnName.substring(0, 1).toUpperCase()
					+ columnName.substring(1);
			if(arguments != null) {
			 types = new Class[1];	
			 types[0] = String.class;			 
			} 
			Method method = recordClass.getMethod(methodName, types);			
			return method.invoke(record, arguments);
		}

		public void printRecords() throws NoSuchMethodException,
				IllegalAccessException, InvocationTargetException {			
			if (records == null || records.size() < 1) {
				return;
			}
			for (Iterator recordsIterator = records.iterator(); recordsIterator
					.hasNext();) {
				Object record = recordsIterator.next();
				for (int j = 0; j < columnNames.length; j++) {
					if (j > 0) {
						out.print("\t");
					}
					String columnName = columnNames[j];
					Object[] arguments = populateArguments(parameters[j]);
					Object columnValue = getColumnValue(record, columnName,
							arguments);
					out.print(formatColumnValue(columnName, columnValue));
				}
				out.println();
			}			
		}

		public Object[] populateArguments(String concatenatedParameters) {
			String[] arguments = null;
			int index = 0;
			if(!concatenatedParameters.equals("")){
			StringTokenizer strToken = new StringTokenizer(concatenatedParameters,",");			
			arguments = new String[strToken.countTokens()];
			while (strToken.hasMoreElements()) {
				arguments[index] = strToken.nextElement().toString();				
				index++;
			}
			}
			return (Object[])arguments;
		}
	}
