package com.eactive.eai.transformer.transform.mapper;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.stream.Stream;

import org.mapstruct.AfterMapping;
import org.mapstruct.CollectionMappingStrategy;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
import org.springframework.beans.factory.annotation.Autowired;

import com.eactive.eai.data.entity.onl.transformer.transform.TransformEntity;
import com.eactive.eai.data.entity.onl.transformer.transform.TransformTypeEntity;
import com.eactive.eai.data.entity.onl.transformer.transform.TransformTypeEntityId;
import com.eactive.eai.data.mapper.GenericMapper;
import com.eactive.eai.transformer.dao.TransformerDaoException;
import com.eactive.eai.transformer.layout.Layout;
import com.eactive.eai.transformer.layout.LayoutManager;
import com.eactive.eai.transformer.transform.Transform;

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = {
		TransformItemEntityMapper.class })
public abstract class TransformEntityMapper implements GenericMapper<Transform, TransformEntity> {

	@Autowired
	private LayoutManager layoutManager;

	@Mapping(source = "cnvsnname", target = "name")
	@Mapping(source = "cnvsndesc", target = "description")
	@Mapping(source = "useyn", target = "useYn")
	@Mapping(source = "transformItemEntities", target = "transformItemList")
	public abstract Transform toVo(TransformEntity entity);

	@InheritInverseConfiguration
	@Override
	public abstract TransformEntity toEntity(Transform vo);

	@AfterMapping
	public void mapTargetLayoutAfterMappingEntity(Transform vo, @MappingTarget TransformEntity entity) {
		Layout targetLayout = vo.getTargetLayout();
		
		TransformTypeEntity transformTypeEntity = new TransformTypeEntity();
		TransformTypeEntityId id = new TransformTypeEntityId();
		id.setCnvsnname(vo.getName());
		id.setLoutname(targetLayout.getName());
		id.setSourcrsultdstcd(Transform.TARGET_LAYOUT);
		transformTypeEntity.setId(id);
		
		transformTypeEntity.setTransformEntity(entity);
		
		if (entity.getTransformTypeEntities() == null) {
			entity.setTransformTypeEntities(new ArrayList<>());
		}
		
		entity.getTransformTypeEntities().add(transformTypeEntity);
	}
	
	@AfterMapping
	public void mapSourceLayoutAfterMappingEntity(Transform vo, @MappingTarget TransformEntity entity) {
		
		Iterator<Layout> it = vo.getSourceLayouts();
		while (it.hasNext() ) {
			Layout sourceLayout = it.next();
			
			TransformTypeEntity transformTypeEntity = new TransformTypeEntity();
			TransformTypeEntityId id = new TransformTypeEntityId();
			id.setCnvsnname(vo.getName());
			id.setLoutname(sourceLayout.getName());
			id.setSourcrsultdstcd(Transform.SOURCE_LAYOUT);
			transformTypeEntity.setId(id);
			
			transformTypeEntity.setTransformEntity(entity);
			
			entity.getTransformTypeEntities().add(transformTypeEntity);
		}
	}

	@AfterMapping
	public void mapTransformItemListAfterMappingVo(TransformEntity entity, @MappingTarget Transform vo) {
		vo.getTransformItemList().stream().forEach(item -> item.setTransform(vo));
	}

	@AfterMapping
	public void mapTargetLayoutAfterMappingVo(TransformEntity entity, @MappingTarget Transform vo) {
		Stream<String> targetLayoutNames = entity.getTransformTypeEntities().stream()
				.filter(targetTransformTypeEntity -> targetTransformTypeEntity.getId().getSourcrsultdstcd()
						.equals(Transform.TARGET_LAYOUT))
				.map(targetTransformTypeEntity -> targetTransformTypeEntity.getId().getLoutname());

		String targetLayoutName = targetLayoutNames.findFirst().orElse(null);

		Layout targetLayout = layoutManager.getLayoutByName(targetLayoutName);
		if (targetLayout == null) {
			throw new TransformerDaoException(
					entity.getCnvsnname() + " - target layout does not exist : " + targetLayoutName);
		}

		vo.setTargetLayout(targetLayout);
	}

	@AfterMapping
	public void mapSourceLayoutAfterMappingVo(TransformEntity entity, @MappingTarget Transform vo) {
		Stream<String> sourceLayoutNames = entity.getTransformTypeEntities().stream()
				.filter(sourceTransformTypeEntity -> sourceTransformTypeEntity.getId().getSourcrsultdstcd()
						.equals(Transform.SOURCE_LAYOUT))
				.map(sourceTransformTypeEntity -> sourceTransformTypeEntity.getId().getLoutname());

		sourceLayoutNames.forEach(sourceLayoutName -> {
			Layout sourceLayout = layoutManager.getLayoutByName(sourceLayoutName);
			if (sourceLayout == null) {
				throw new TransformerDaoException(
						entity.getCnvsnname() + " - source layout does not exist : " + sourceLayoutName);
			}
			vo.addSourceLayout(sourceLayout);
		});
	}

}
