package com.zjrs.appcomm.template.excel.builder;

import com.zjrs.appcomm.template.excel.mapper.CellStyler;
import com.zjrs.appcomm.template.excel.mapper.FieldCellStyler;
import com.zjrs.appcomm.template.excel.mapper.RowStyler;
import com.zjrs.appcomm.template.excel.mapper.SheetCoordinate;
import com.zjrs.appcomm.template.excel.mapper.SimpleDataCellStyler;
import com.zjrs.appcomm.template.excel.mapper.SimpleDataRowStyler;
import com.zjrs.appcomm.template.excel.mapper.SimpleHeaderCellStyler;
import com.zjrs.appcomm.template.excel.mapper.SimpleHeaderRowStyler;
import com.zjrs.appcomm.template.excel.util.ExcelUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExportBuilder<D, L> {
	
	private ExportDefinition<D, L> exportDefinition;
	public ExportBuilder(Class<D> discreteClass, Class<L> listClass) {
		this.exportDefinition = new ExportDefinition<>(discreteClass, listClass);
		this.exportDefinition.setListHeaderRowIndex(0);
		this.exportDefinition.setListHeaderRowStyler(new SimpleHeaderRowStyler());
		this.exportDefinition.setListHeaderCellStyler(new SimpleHeaderCellStyler());
		this.exportDefinition.setListDataRowIndex(1);
		this.exportDefinition.setListDataRowStyler(new SimpleDataRowStyler());
		this.exportDefinition.setListDataCellStyler(new SimpleDataCellStyler());
	}
	
	public ExportDefinition<D, L> build() {
		return exportDefinition;
	}
	
	/* Excel中Sheet */
	public ExportBuilder<D, L> sheet(Sheet sheet) {
		exportDefinition.setSheet(sheet);
		return this;
	}
	public ExportBuilder<D, L> sheet(Workbook workbook, String sheetName) {
		Sheet sheet = ExcelUtils.getSheet(workbook, sheetName, true);
		return sheet(sheet);
	}
	public ExportBuilder<D, L> sheet(InputStream is, String sheetName) throws IOException, InvalidFormatException {
		Workbook workbook = WorkbookFactory.create(is);
		return sheet(workbook, sheetName);
	}
	public ExportBuilder<D, L> sheet(byte[] content, String sheetName) throws IOException, InvalidFormatException {
		try (InputStream is = new ByteArrayInputStream(content)) {
			return sheet(is, sheetName);
		}
	}
	public ExportBuilder<D, L> sheet(String sheetName) throws IOException {
		Workbook workbook = new XSSFWorkbook();
		return sheet(workbook, sheetName);
	}
	
	/* 离散数据 */
	public ExportBuilder<D, L> discreteData(D discreteData) {
		exportDefinition.setDiscreteData(discreteData);
		return this;
	}
	
	/* 离散数据坐标 */
	public ExportBuilder<D, L> discreteFieldCoordinates(Map<String, SheetCoordinate> discreteFieldCoordinates) {
		exportDefinition.setDiscreteFieldCoordinates(discreteFieldCoordinates);
		return this;
	}
	public ExportBuilder<D, L> putDiscreteFieldCoordinate(String fieldName, SheetCoordinate discreteFieldCoordinate) {
		if (exportDefinition.getDiscreteFieldCoordinates() == null) {
			exportDefinition.setDiscreteFieldCoordinates(new HashMap<>());
		}
		exportDefinition.getDiscreteFieldCoordinates().put(fieldName, discreteFieldCoordinate);
		return this;
	}
	public ExportBuilder<D, L> putDiscreteFieldCoordinate(String fieldName, int row, int col) {
		putDiscreteFieldCoordinate(fieldName, new SheetCoordinate(row, col));
		return this;
	}
	public ExportBuilder<D, L> putDiscreteFieldCoordinate(String fieldName, int row, int col, CellStyler styler) {
		putDiscreteFieldCoordinate(fieldName, new SheetCoordinate(row, col, styler));
		return this;
	}
	
	/* 离散数据单元格默认样式处理 */
	public ExportBuilder<D, L> discreteDefaultDataStyler(CellStyler discreteDefaultDataStyler) {
		exportDefinition.setDiscreteDefaultDataStyler(discreteDefaultDataStyler);
		return this;
	}
	
	/* 列表数据表头所在行下标 */
	public ExportBuilder<D, L> listHeaderRowIndex(int listHeaderRowIndex) {
		exportDefinition.setListHeaderRowIndex(listHeaderRowIndex);
		return this;
	}
	
	/* 列表数据表头名称 */
	public ExportBuilder<D, L> listHeaders(String[][] listHeaders) {
		exportDefinition.setListHeaders(listHeaders);
		return this;
	}
	public ExportBuilder<D, L> listHeaders(String[] listHeaders) {
		exportDefinition.setListHeaders(new String[][] { listHeaders });
		return this;
	}
	public ExportBuilder<D, L> listHeaders(List<?> listHeaders) {
		if (listHeaders.size() == 0) {
			listHeaders(new String[0]);
		}
		if (listHeaders.get(0) instanceof String) {
			listHeaders(listHeaders.toArray(new String[0]));
		} else if (listHeaders.get(0) instanceof List) {
			String[][] listHeadersA = new String[listHeaders.size()][];
			for (int i = 0; i < listHeaders.size(); i++) {
				listHeadersA[i] = ((List<?>) listHeaders.get(i)).toArray(new String[0]);
			}
			listHeaders(listHeadersA);
		}
		return this;
	}
	
	/* 列表数据字段映射 */
	public ExportBuilder<D, L> listFields(String[] listFields) {
		exportDefinition.setListFields(listFields);
		return this;
	}
	public ExportBuilder<D, L> listFields(List<String> listFields) {
		listFields(listFields.toArray(new String[0]));
		return this;
	}
	
	/* 列表数据表头行样式处理 */
	public ExportBuilder<D, L> listHeaderRowStyler(RowStyler listHeaderRowStyler) {
		exportDefinition.setListHeaderRowStyler(listHeaderRowStyler);
		return this;
	}
	
	/* 列表数据表头单元格样式处理 */
	public ExportBuilder<D, L> listHeaderCellStyler(CellStyler listHeaderCellStyler) {
		exportDefinition.setListHeaderCellStyler(listHeaderCellStyler);
		return this;
	}
	
	/* 列表数据的起始行下标 */
	public ExportBuilder<D, L> listDataRowIndex(int listDataRowIndex) {
		exportDefinition.setListDataRowIndex(listDataRowIndex);
		return this;
	}
	
	/* 列表数据 */
	public ExportBuilder<D, L> listData(List<L> listData) {
		exportDefinition.setListData(listData);
		return this;
	}
	
	/* 列表数据行样式处理 */
	public ExportBuilder<D, L> listDataRowStyler(RowStyler listDataRowStyler) {
		exportDefinition.setListDataRowStyler(listDataRowStyler);
		return this;
	}
	
	/* 列表数据单元格样式处理 */
	public ExportBuilder<D, L> listDataCellStyler(CellStyler listDataCellStyler) {
		exportDefinition.setListDataCellStyler(listDataCellStyler);
		return this;
	}
	public ExportBuilder<D, L> addListDataCellStyler(CellStyler listDataCellStyler) {
		addListDataCellStyler(FieldCellStyler.MUTIL_FIELD, listDataCellStyler);
		return this;
	}
	public ExportBuilder<D, L> addListDataCellStyler(String field, CellStyler listDataCellStyler) {
		CellStyler source = exportDefinition.getListDataCellStyler();
		if (source == null) {
			source = new FieldCellStyler();
			listDataCellStyler(source);
		} else if (!(source instanceof FieldCellStyler)) {
			FieldCellStyler fieldCellStyler = new FieldCellStyler();
			fieldCellStyler.addCellStyler(FieldCellStyler.MUTIL_FIELD, source);
			listDataCellStyler(fieldCellStyler);
			source = fieldCellStyler;
		}
		FieldCellStyler fieldCellStyler = (FieldCellStyler) source;
		fieldCellStyler.addCellStyler(field, listDataCellStyler);
		return this;
	}
}
