package com.eactive.eai.transformer.dao.excel;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eactive.eai.data.entity.onl.transformer.function.Function;
import com.eactive.eai.transformer.dao.TransformerDaoException;
import com.eactive.eai.transformer.function.FunctionDefinition;
import com.eactive.eai.transformer.function.ParameterDefinition;
import com.eactive.eai.transformer.function.loader.FunctionLoader;
import com.eactive.eai.transformer.function.mapper.FunctionMapper;
import com.eactive.eai.transformer.util.ConstantUtil;

@Service
public class FunctionExcelDao extends BaseExcelDao<String, FunctionDefinition> {

	@Autowired
	private FunctionLoader functionLoader;

	private static final int DATA_ROW_OFFSET = 10;
	private static final int COL_FUNC_NAME = 1;
	private static final int COL_FUNC_DESC = 2;
	private static final int COL_RETN_TYPE = 3;
	private static final int COL_FUNC_TYPE = 4;
	private static final int COL_FUNC_CLAS = 5;
	private static final int COL_PARA_NAME = 6;
	private static final int COL_PARA_DESC = 7;
	private static final int COL_PARA_TYPE = 8;

	@Autowired
	private FunctionMapper functionMapper;

	public FunctionExcelDao() {
		super("function");
	}

	protected Map<String, FunctionDefinition> parse(Sheet[] sheets) {
		Sheet sheet = sheets[0];

		Map<String, FunctionDefinition> map = new TreeMap<>();

		int pc = 1;
		FunctionDefinition fd = null;
		ParameterDefinition pd = null;

		try {
			for (int currentRow = DATA_ROW_OFFSET; sheet.existsRow(currentRow); currentRow++) {
				try {
					String funcName = sheet.getCellString(currentRow, COL_FUNC_NAME);
					String paraName = sheet.getCellString(currentRow, COL_PARA_NAME);
					if (funcName.trim().length() > 0) {
						fd = new FunctionDefinition();
						fd.setName(funcName);
						fd.setDescription(sheet.getCellString(currentRow, COL_FUNC_DESC));
						fd.setReturnTypeId(
								ConstantUtil.getDataTypeId(sheet.getCellString(currentRow, COL_RETN_TYPE), ""));
						fd.setFunctionTypeId(
								ConstantUtil.getFunctionTypeId(sheet.getCellString(currentRow, COL_FUNC_TYPE)));
						fd.setFunctionClass(sheet.getCellString(currentRow, COL_FUNC_CLAS));

						/**
						 * set overwrite
						 */
						boolean overwrite = sheet.isEquals(6, 4, "O");
						fd.setOverwrite(overwrite);

						map.put(fd.getName(), fd);
						pc = 1;

						if (paraName.trim().length() > 0) {
							pd = new ParameterDefinition();
							pd.setFunctionName(fd.getName());
							pd.setName(sheet.getCellString(currentRow, COL_PARA_NAME));
							pd.setDescription(sheet.getCellString(currentRow, COL_PARA_DESC));
							pd.setTypeId(
									ConstantUtil.getDataTypeId(sheet.getCellString(currentRow, COL_PARA_TYPE), ""));
							pd.setSeqNo(pc++);

							fd.addParameter(pd);
						}
					} else if (fd != null && paraName.trim().length() > 0) {
						pd = new ParameterDefinition();
						pd.setFunctionName(fd.getName());
						pd.setName(sheet.getCellString(currentRow, COL_PARA_NAME));
						pd.setDescription(sheet.getCellString(currentRow, COL_PARA_DESC));
						pd.setTypeId(ConstantUtil.getDataTypeId(sheet.getCellString(currentRow, COL_PARA_TYPE), ""));
						pd.setSeqNo(pc++);

						fd.addParameter(pd);
					} else {
						break;
					}
				} catch (Exception e) {
					logger.error("[ERROR] !!!!! " + e.getMessage() + " - ROW: " + currentRow, e);
				}
			}
		} catch (Exception e) {
			throw new TransformerDaoException(e.getMessage(), e);
		}

		return map;
	}

	public FunctionDefinition findFunctionByName(String functionName) {
		return null;
	}

	protected Map<String, FunctionDefinition> loadSheets(Sheet[] sheets) {
		Map<String, FunctionDefinition> map = parse(sheets);
		return map;
	}

	protected Map<String, FunctionDefinition> removeSheets(Sheet[] sheets) {
		List<Function> functions = functionLoader.findAll();
		int functionSize = functions.size();
		functionLoader.deleteAll(functions);

		if (logger.isInfoEnabled()) {
			logger.info("총 " + functionSize + " 개의 FunctionDefinition 데이터를 삭제했습니다.");
		}

		return null;
	}

	public void save(Map<String, FunctionDefinition> functionMap) {
		if (logger.isInfoEnabled()) {
			logger.info("    + save functions");
		}

		for (Iterator<FunctionDefinition> fitr = functionMap.values().iterator(); fitr.hasNext();) {
			FunctionDefinition fd = fitr.next();

			if (fd.getOverwrite()) {
				functionLoader.findById(fd.getName())
						.ifPresent(function -> functionLoader.delete(function));
			}

			Function function = functionMapper.toEntity(fd);
			functionLoader.save(function);
		}
	}

}
