package cn.report.excel.easyexcel.custom.base;

import java.math.BigInteger;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
import cn.report.excel.easyexcel.api.metadata.Head;
import cn.report.excel.easyexcel.api.write.handler.CellWriteHandler;
import cn.report.excel.easyexcel.api.write.metadata.holder.WriteSheetHolder;
import cn.report.excel.easyexcel.api.write.metadata.holder.WriteTableHolder;


/**导出样式配置类，需要继承（CellWriteHandler）写入handler类来重写里边的方法做逻辑处理，
 * 支持隐藏列，锁定列，表单保护密码，表单背景颜色，数据格式校验限制等
 */

public class ExcelStyleConfig implements CellWriteHandler
{
	//是否锁定整个sheet
	private Boolean lockFlag = false;
	/**
	 * 需要锁定的列集合
	 */
	private List<Integer> columnList;
	/**
	 * 样式类
	 */
	private CellStyle cellStyle;
	/**
	 * 隐藏索引数
	 */
	private List<Integer> hiddenIndices;
	/**
	 * 限制那一列为数值型 开头结尾
	 */
	private List<Integer> columnNumList;
	/**
	 * 限制哪一行为数值开头结尾集合
	 */
	private List<Integer> rowNumList;
	/**
	 * hiddenIndices 隐藏的列
	 * columnList 锁定列集合
	 * columnNumList 列为数值型 开头结尾
	 * rowNumList 行为数值开头结尾集合
	 * */
	public ExcelStyleConfig(List<Integer> columnList, 
			List<Integer> columnNumList, 
			List<Integer> hiddenIndices,
			List<Integer> rowNumList) {
		this.columnList = columnList;
		this.hiddenIndices = hiddenIndices;
		this.columnNumList = columnNumList;
		this.rowNumList = rowNumList;
	}

	public ExcelStyleConfig(Boolean lockFlag, 
			List<Integer> columnNumList, 
			List<Integer> hiddenIndices,
			List<Integer> rowNumList)
	{
		this.lockFlag = lockFlag;
		this.hiddenIndices = hiddenIndices;
		this.columnNumList = columnNumList;
		this.rowNumList = rowNumList;
	
	}
	
	public ExcelStyleConfig(List<Integer> columnList) {
		this.columnList = columnList;
	}
	public ExcelStyleConfig(List<Integer> columnList, List<Integer> columnNumList) {
		this.columnList = columnList;
		this.columnNumList = columnNumList;
	}
	public ExcelStyleConfig(List<Integer> columnList, List<Integer> columnNumList, List<Integer> hiddenIndices) {
		this.columnList = columnList;
		this.columnNumList = columnNumList;
		this.hiddenIndices = hiddenIndices;
	}
	@Override
	public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
		cellStyle = writeSheetHolder.getSheet().getWorkbook().createCellStyle();
	}

	/*sheet.createFreezePane(int cellNum,int rowNum,int firstCellNum,int firstRollNum );
	四个参数分别代表:
		cellNum:表示要冻结的列数；
		rowNum:表示要冻结的行数；
		firstCellNum:表示被固定列右边第一列的列号；
		firstRollNum :表示被固定行下边第一列的行号;
	 */
	@Override
	public void afterCellCreate(WriteSheetHolder writeSheetHolder, 
			WriteTableHolder writeTableHolder, 
			Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) 
	{
		Sheet sheet = writeSheetHolder.getSheet();
		//设置冻结某行某列
		//sheet.createFreezePane(colSplit, rowSplit);

		// 下边框
		cellStyle.setBorderBottom(BorderStyle.THIN);
		// 左边框
		cellStyle.setBorderLeft(BorderStyle.THIN);
		// 上边框
		cellStyle.setBorderTop(BorderStyle.THIN);
		// 右边框
		cellStyle.setBorderRight(BorderStyle.THIN);
		// 水平对齐方式
		cellStyle.setAlignment(HorizontalAlignment.CENTER);
		// 垂直对齐方式
		cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		cellStyle.setLocked(false);

		//设置隐藏列
		if (!CollectionUtils.isEmpty(hiddenIndices)
				&& hiddenIndices.contains(cell.getColumnIndex())) {
			writeSheetHolder.getSheet().setColumnHidden(cell.getColumnIndex(), true);
		}
		
		//锁定整个sheet
		if (lockFlag){
			writeSheetHolder.getSheet().protectSheet("password");
		}
		
		//设置锁定列 有问题，原因不明 
		if (!CollectionUtils.isEmpty(columnList) 
			&& columnList.contains(cell.getColumnIndex())) 
		{
		 // 设置锁定单元格
		 cellStyle.setLocked(true);
		 //设置背景颜色GREY_25_PERCENT
		 cellStyle.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
		 cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		 cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
		 cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		 //设置表单保护密码
		 writeSheetHolder.getSheet().protectSheet("password");
		}
		
		//限制数字
		if (!CollectionUtils.isEmpty(columnNumList) 
				&& columnNumList.contains(cell.getColumnIndex())) 
		{
			// --- 数据有效性 只允许输入整数 ---
			DataValidationHelper helper = sheet.getDataValidationHelper();
			//校验数值格式 只能输入整数0 -xx 范围内
			DataValidationConstraint constraintNum = new XSSFDataValidationConstraint(
					DataValidationConstraint.ValidationType.INTEGER,
					DataValidationConstraint.OperatorType.BETWEEN, "0", "100000000");
			CellRangeAddressList regionNumber = new CellRangeAddressList(
					BigInteger.ONE.intValue(), 
					rowNumList.get(rowNumList.size() - 1), 
					columnNumList.get(0), 
					columnNumList.get(columnNumList.size() - 1));
			DataValidation validationNum = helper.createValidation(constraintNum, regionNumber);
			//输入错误提示
			validationNum.createErrorBox("输入值错误", "请输入0-100000000之间的数字");
			validationNum.setShowErrorBox(true);
			sheet.addValidationData(validationNum);
		}
		// 填充单元格样式
		cell.setCellStyle(cellStyle);
	}

}
