/*
 * Copyright 2006-2011 the Seasar Foundation and the Others.
 *
 * 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 org.seasar.codegen.unit;

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.HSSFFont;
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
 * @author azusa
 * 
 */
public class XlsWriterExt implements DataWriter, DataSetConstants {

    private OutputStream out_;

    private HSSFWorkbook workbook_;

    private HSSFCellStyle dateStyle_;

    private HSSFCellStyle base64Style_;

    public XlsWriterExt(String path) {
        this(new File(ResourceUtil.getResourceAsFile("."), path));
    }

    public XlsWriterExt(String dirName, String fileName) {
        this(ResourceUtil.getResourceAsFile(dirName), fileName);
    }

    public XlsWriterExt(File dir, String fileName) {
        this(new File(dir, fileName));
    }

    public XlsWriterExt(File file) {
        this(FileOutputStreamUtil.create(file));
    }

    public XlsWriterExt(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));
    }

    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);
                        if (hasError(value)) {
                            HSSFCellStyle style = workbook_.createCellStyle();
                            HSSFFont font = workbook_.createFont();
                            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
                            font.setColor(HSSFFont.COLOR_RED);
                            style.setFont(font);
                            cell.setCellStyle(style);
                        }
                    }
                }
            }
        }
        try {
            workbook_.write(out_);
            out_.flush();
        } catch (IOException ex) {
            throw new IORuntimeException(ex);
        } finally {
            try {
                out_.close();
            } catch (Exception ignore) {
            }
        }
    }

    private boolean hasError(Object value) {
        if (value instanceof String) {
            if (((String) value).indexOf("expect") != -1) {
                return true;
            }
        }
        return false;
    }

    private void setValue(HSSFCell cell, Object value) {
        if (value instanceof Number) {
            cell.setCellValue(value.toString());
        } 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));
        }
    }
}
