/**
 *   Copyright 2007 Y.Murakamin
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package net.murakamin.csv;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

import net.murakamin.csv.exception.CSVParseException;

import org.supercsv.io.CsvListReader;
import org.supercsv.prefs.CsvPreference;

/**
 * Parse of the CSV data is done. The CSV file is done, and the handler call or
 * the ResultSet object of every the Parse doing and one line is worn and the
 * handler call of every the Parse doing and one line is done.
 * 
 * @author Y.Murakamin
 * @see net.murakamin.csv.CSVDataHandler
 */
public class CSVParser
{

	public static final char QUOTE_NONE = 0x00;

	private final CSVDataHandler handler;

	/**
	 * constractor
	 * 
	 * @param importTarget
	 *            Object that implements handler that notifies CSV Parse result
	 */
	public CSVParser(final CSVDataHandler importTarget)
	{
		super();
		handler = importTarget;
	}

	/**
	 * Perse does the CSV file.
	 * 
	 * @param source
	 *            target CSV file
	 * @throws CSVParseException
	 */
	public void doParse(final File source) throws CSVParseException
	{
		CsvListReader reader = null;
		List<String> currentDatas = null;
		try
		{
			CsvPreference pref = new CsvPreference(this.handler.getQuote(),
			        this.handler.getSeparator(), "\n");

			reader = new CsvListReader(new BufferedReader(
			        new InputStreamReader(new FileInputStream(source),
			                this.handler.getFileCharset())), pref);

			if (this.handler.isHeader())
			{
				reader.getCSVHeader(true);
			}

			while ((currentDatas = reader.read()) != null)
			{
				this.handler.addCSVData(currentDatas.toArray(new String[0]));
			}
		} catch (Exception e)
		{
			if (reader == null)
			{
				throw new CSVParseException(e);
			} else
			{
				throw new CSVParseException(reader.getLineNumber(), e);
			}

		}
	}

	/**
	 * Perse does the ResultSet object
	 * 
	 * @param source
	 *            target ResultSet Object
	 * @throws CSVParseException
	 */
	public void doParse(final ResultSet source) throws CSVParseException
	{
		int lineNo = 0;
		String[] currentDatas = null;
		try
		{
			for (lineNo = 1; source.next(); lineNo++)
			{
				currentDatas = this.parseStrings(source);

				this.handler.addCSVData(currentDatas);
			}
		} catch (Exception e)
		{
			throw new CSVParseException(lineNo, e);
		}
	}

	private String[] parseStrings(final ResultSet rs)
	        throws UnsupportedEncodingException, SQLException
	{
		ResultSetMetaData metaData = rs.getMetaData();
		int columnCount = metaData.getColumnCount();
		String[] csvData = null;
		csvData = new String[columnCount];
		for (int i = 1; i < columnCount + 1; i++)
		{
			Object o = rs.getObject(i);

			csvData[i - 1] = null;
			if (o != null)
			{
				csvData[i - 1] = o.toString();
			}
		}

		return csvData;
	}
}
