package kcg.faics.cmmn.excel;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 엑셀 변환 클래스.
 * 
 * @author kimnomin
 *
 * @param <T> 데이터 VO
 */
public class ExcelExporter<T> extends AbstractExcelExport {

	/**
	 * 헤더 맵 객체. 
	 * <해당 VO의 멤버변수명, 값> 형태
	 * ex) {title: 제목} 
	 * 
	 * 해당 맵 객체에 입력된 순서대로 엑셀이 생성된다.
	 * 
	 * !! 주의 !! 해당 맵 객체의 key가 데이터 VO의 멤버변수명과 동일해야 한다. 
	 */
	private LinkedHashMap<String, String> headers;
	/**
	 * 데이터 VO List.
	 */
	private List<T> list;
	/**
	 * 엑셀 내 표현될 제목.
	 */
	private String title;

	/**
	 * 생성자.
	 * 
	 * @param headers 헤더 맵 객체.
	 * @param list 데이터 VO List.
	 * @param title 엑셀 내 표현될 제목.
	 */
	public ExcelExporter(final LinkedHashMap<String, String> headers, final List<T> list,
			final String title) {
		super();
		this.headers = headers;
		this.list = list;
		this.title = title;
	}

	@Override
	public XSSFWorkbook makeExcel(final XSSFWorkbook wb) {
		if (list.size() <= 0 || headers.size() <= 0) {
			return null;
		}

		XSSFSheet sheet = null;
		XSSFRow row = null;
		XSSFCell cell = null;

		ExcelStyle style = new ExcelStyle(wb);
		sheet = wb.createSheet(title);
		setTitleRow(sheet, style.titleStyle, title);

		Set<String> keySet = headers.keySet();

		// 헤더
		int loopIdx = 0;
		row = sheet.createRow(firstRow);
		cell = row.createCell(loopIdx);
		cell.setCellValue("번호");
		cell.setCellStyle(style.headerStyle);
		loopIdx++;
		for (String key : keySet) {
			cell = row.createCell(loopIdx);
			cell.setCellValue(headers.get(key));
			cell.setCellStyle(style.headerStyle);
			loopIdx++;
		}

		// 값
		for (int i = 0; i < list.size(); i++) {
			T t = list.get(i);
			row = sheet.createRow(firstRow + 1 + i);
			
			loopIdx = 0;
			cell = row.createCell(loopIdx);
			cell.setCellValue(i + 1);
			cell.setCellStyle(style.normalTextStyle);
			loopIdx++;
			for (String key : keySet) {
				String value = "";

				try {
					if (t instanceof Map<?, ?>) {
						Object o = ((Map<?, ?>) t).get(key.toLowerCase());
						if (o instanceof String) {
							value = o.toString();
						} else if (o instanceof Integer || o instanceof Double || o instanceof Long) {
							value = String.valueOf(o);
						} else if (o instanceof BigDecimal) {
							value = ((BigDecimal) o).toString();
						}
					} else { 
						Field f = t.getClass().getDeclaredField(key);
						f.setAccessible(true);
						Object val = f.get(t);
						if (val != null) {
							value = val.toString();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

				cell = row.createCell(loopIdx);
				cell.setCellValue(value);
				cell.setCellStyle(style.normalTextStyle);
				loopIdx++;
			}
		}

		return wb;
	}
}
