package org.seasar.extension.dataset.impl;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.seasar.extension.dataset.DataRow;
import org.seasar.extension.dataset.DataSet;
import org.seasar.extension.dataset.DataSetConstants;
import org.seasar.extension.dataset.DataTable;
import org.seasar.extension.dataset.DataWriter;
import org.seasar.framework.exception.IORuntimeException;
import org.seasar.framework.util.Base64Util;
import org.seasar.framework.util.FileOutputStreamUtil;
import org.seasar.framework.util.ResourceUtil;
import org.seasar.framework.util.StringConversionUtil;

/**
 * @author higa
 *
 */
public class XlsWriter implements DataWriter, DataSetConstants {

	private OutputStream out_;
	private HSSFWorkbook workbook_;
	private HSSFCellStyle dateStyle_;
	private HSSFCellStyle base64Style_;
	
	public XlsWriter(String path) {
		File file = new File(ResourceUtil.getResourceAsFile("."), path);
		setOutputStream(FileOutputStreamUtil.create(file));
	}
	
	public XlsWriter(OutputStream out) {
		setOutputStream(out);
	}
	
	public void setOutputStream(OutputStream out) {
		out_ = out;
		workbook_ = new HSSFWorkbook();
		HSSFDataFormat df = workbook_.createDataFormat();
		dateStyle_ = workbook_.createCellStyle();
		dateStyle_.setDataFormat(df.getFormat(DATE_FORMAT));
		base64Style_ = workbook_.createCellStyle();
		base64Style_.setDataFormat(df.getFormat(BASE64_FORMAT));
	}

	/**
	 * @see org.seasar.extension.dataset.DataWriter#write(org.seasar.extension.dataset.DataSet)
	 */
	public void write(DataSet dataSet) {
		for (int i = 0; i < dataSet.getTableSize(); ++i){
			DataTable table = dataSet.getTable(i);
			HSSFSheet sheet = workbook_.createSheet();
			workbook_.setSheetName(i, table.getTableName(), HSSFWorkbook.ENCODING_UTF_16);
			HSSFRow headerRow = sheet.createRow(0);
			for (int j = 0; j < table.getColumnSize(); ++j) {
				HSSFCell cell = headerRow.createCell((short) j);
				cell.setCellValue(table.getColumnName(j));
			}
			for (int j = 0; j < table.getRowSize(); ++j) {
				HSSFRow row = sheet.createRow(j + 1);
				for (int k = 0; k < table.getColumnSize(); ++k) {
					DataRow dataRow = table.getRow(j);
					Object value = dataRow.getValue(k);
					if (value != null) {
						HSSFCell cell = row.createCell((short) k);
						setValue(cell, value);
					}
				}
			}
		}
		try {
			workbook_.write(out_);
			out_.flush();
			out_.close();
		} catch (IOException ex) {
			throw new IORuntimeException(ex);
		}
	}
	
	private void setValue(HSSFCell cell, Object value) {
		if (value instanceof Number) {
			cell.setCellValue(((Number) value).doubleValue());
		} else if (value instanceof Date) {
			cell.setCellValue((Date) value);
			cell.setCellStyle(dateStyle_);
		} else if (value instanceof byte[]) {
			cell.setCellValue(Base64Util.encode((byte[]) value));
			cell.setCellStyle(base64Style_);
		} else if (value instanceof Boolean) {
            cell.setCellValue(((Boolean)value).booleanValue());
		} else {
			cell.setEncoding(HSSFWorkbook.ENCODING_UTF_16);
			cell.setCellValue(StringConversionUtil.toString(value, null));
		}
	}
}
