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

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

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

import com.eactive.eai.data.entity.onl.transformer.transform.TransformEntity;
import com.eactive.eai.transformer.dao.TransformerDaoException;
import com.eactive.eai.transformer.dao.jdbc.LayoutJdbcDao;
import com.eactive.eai.transformer.layout.Layout;
import com.eactive.eai.transformer.layout.LayoutManager;
import com.eactive.eai.transformer.transform.Transform;
import com.eactive.eai.transformer.transform.TransformItem;
import com.eactive.eai.transformer.transform.TransformValidator;
import com.eactive.eai.transformer.transform.loader.TransformLoader;
import com.eactive.eai.transformer.transform.mapper.TransformEntityMapper;

@Service
@Transactional
public class TransformExcelDao extends BaseExcelDao<String, Transform> {
	private static final int DATA_ROW_OFFSET = 13;
	private static final int COL_TRAN_INFO = 2;
	private static final int ROW_TRAN_NAME = 8;
	private static final int ROW_TRAN_DESC = 9;
	private static final int ROW_TRAN_TRG_LOUT = 10;
	private static final int ROW_TRAN_SRC_LOUT = 11;

	private static final int COL_INST = 2;
	private static final int COL_RES_PATH = 3;
	private static final int COL_SEQ = 4;
	private static final int COL_DEF_VALU = 5;

	@Autowired
	private LayoutManager layoutManager;

	@Autowired
	private TransformLoader transformLoader;

	@Autowired
	private TransformEntityMapper transformEntityMapper;
	
	@Autowired
	private LayoutJdbcDao layoutJdbcDao;

	public TransformExcelDao() {
		super("transform");
	}

	protected Map<String, Transform> parse(Sheet[] sheets) {
		Transform transform = new Transform();

		Sheet sheet = sheets[0];

		// 변환 기본 정보
		try {
			transform.setName(sheet.getCellString(ROW_TRAN_NAME, COL_TRAN_INFO));
			transform.setDescription(sheet.getCellString(ROW_TRAN_DESC, COL_TRAN_INFO));
			transform.setLastUpdateDate(getCurrentDateTime().substring(0, 16));

			String targetLayoutName = sheet.getCellString(ROW_TRAN_TRG_LOUT, COL_TRAN_INFO);
			Layout targetLayout = layoutManager.getLayoutByName(targetLayoutName);

			if (targetLayout == null) {
				targetLayout = layoutJdbcDao.load(targetLayoutName);
				if (targetLayout == null)
					throw new Exception("해당 TARGET LAYOUT을 찾을 수 없습니다. - " + targetLayoutName);
				layoutManager.putLayout(targetLayout);
			}

			transform.setTargetLayout(targetLayout);

			String sourceLayoutNames = sheet.getCellString(ROW_TRAN_SRC_LOUT, COL_TRAN_INFO);
			StringTokenizer tokens = new StringTokenizer(sourceLayoutNames, "\n");

			while (tokens.hasMoreTokens()) {
				String sourceLayoutName = tokens.nextToken().trim();
				Layout sourceLayout = layoutManager.getLayoutByName(sourceLayoutName);

				if (sourceLayout == null) {
					sourceLayout = layoutJdbcDao.load(sourceLayoutName);
					if (sourceLayout == null)
						throw new Exception("해당 SOURCE LAYOUT을 찾을 수 없습니다. - " + sourceLayoutName);
					layoutManager.putLayout(sourceLayout);
				}

				transform.addSourceLayout(sourceLayout);
			}

			for (int currentRow = DATA_ROW_OFFSET; sheet.existsRow(currentRow); currentRow++) {
				TransformItem item = new TransformItem();
				item.setTransform(transform);
				item.setResultItemPath(sheet.getCellString(currentRow, COL_RES_PATH));
				item.setInstruction(sheet.getCellString(currentRow, COL_INST));
				item.setDefaultValue(sheet.getCellString(currentRow, COL_DEF_VALU));

				if ("".equals(item.getResultItemPath().trim()))
					break;

				try {
					item.setSeqNo(sheet.getCellInt(currentRow, COL_SEQ));
				} catch (Exception e) {
					item.setSeqNo(999);
				}
				transform.addTransformItem(item);
			}

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

			Map<String, Transform> map = new TreeMap<>();
			map.put(transform.getName(), transform);
			return map;
		} catch (Exception e) {
			throw new TransformerDaoException(e.getMessage(), e);
		}
	}

	public Transform findTransformByName(String transformName) {
		return null;
	}

	/**
	 * ExcelJob Interface
	 */
	protected Map<String, Transform> loadSheets(Sheet[] sheets) {
		return parse(sheets);
	}

	protected Map<String, Transform> removeSheets(Sheet[] sheets) throws Exception {
		String transformName = sheets[0].getCellString(ROW_TRAN_NAME, COL_TRAN_INFO);
		transformLoader.deleteById(transformName);
		return null;
	}

	public void save(Map<String, Transform> transformMap) throws Exception {
		for (Iterator<Transform> iter = transformMap.values().iterator(); iter.hasNext();) {
			Transform transform = iter.next();
			TransformValidator.validate(transform, true);
			saveTransform(transform);
		}
	}

	public void saveTransform(final Transform transform) {
		if (transform == null) {
			return;
		}

		if (logger.isInfoEnabled()) {
			logger.info("    + save transform | %s" + transform.getName());
		}

		/**
		 * overwrite?
		 */
		if (transform.getOverwrite()) {
			transformLoader.findById(transform.getName()).ifPresent(transformLoader::delete);
		}

		TransformEntity transformEntity = transformEntityMapper.toEntity(transform);
		transformLoader.save(transformEntity);

	}

}
