package com.eactive.eai.rms.data.entity.onl.adapter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.entity.onl.adapter.AdapterGroup;
import com.eactive.eai.data.jpa.AbstractDataService;
import com.querydsl.core.types.dsl.BooleanExpression;

@Service
@Transactional
public class AdapterTypePropertyService extends AbstractDataService<AdapterTypeProperty, AdapterTypePropertyId, AdapterTypePropertyRepository> {

	public Iterable<AdapterTypeProperty> findByAdapterGroup(AdapterGroup adapterGroup) {
		return findByIdAdptrCdAndAdptrIoDstcd(adapterGroup.getAdptrcd(), adapterGroup.getAdptriodstcd());
	}
	
	public Iterable<AdapterTypeProperty> findByIdAdptrCdAndAdptrIoDstcd(String adptrCd, String adptrIoDstcd) {
		QAdapterTypePropertyId id = QAdapterTypeProperty.adapterTypeProperty.id;
		BooleanExpression predicate = id.adptrCd.eq(adptrCd).and(id.adptrIoDstcd.eq(adptrIoDstcd));
		return repository.findAll(predicate, Sort.by("id.adptrPrptyName"));
	}

	public Iterable<AdapterTypeProperty> findByAdptrCd(String adptrCd) {
		QAdapterTypePropertyId id = QAdapterTypeProperty.adapterTypeProperty.id;
		return repository.findAll(id.adptrCd.eq(adptrCd), Sort.by("id.adptrCd", "id.adptrIoDstcd", "id.adptrPrptyName"));
	}

	public void deleteOrSave(String adptrCd, List<AdapterTypeProperty> newAdapterTypeProperties) {
		Iterable <AdapterTypeProperty> existingProperties = findByAdptrCd(adptrCd);
		
		List<AdapterTypeProperty> propertiesToDelete = new ArrayList<>();
		existingProperties.forEach(propertiesToDelete::add);
		propertiesToDelete.removeAll(newAdapterTypeProperties);
		deleteAll(propertiesToDelete);
		
		saveOrUpdateProperties(existingProperties, newAdapterTypeProperties);
	}

	private void saveOrUpdateProperties(Iterable <AdapterTypeProperty> existingProperties, List<AdapterTypeProperty> newProperties) {
		
		Map<AdapterTypePropertyId, AdapterTypeProperty> existingPropertiesMap  = StreamSupport
				.stream(existingProperties.spliterator(), false)
				.collect(Collectors.toMap(AdapterTypeProperty::getId, property -> property));
		
		newProperties.forEach(newProperty -> {
			AdapterTypeProperty existingProperty = existingPropertiesMap.get(newProperty.getId());
			
			if(existingProperty != null) {	// update
				existingProperty.setDmnKnd(newProperty.getDmnKnd());
				existingProperty.setAdptrPrptyDesc(newProperty.getAdptrPrptyDesc());
				repository.save(existingProperty);
			} else {	// insert
				repository.save(newProperty);
			}
		});
		
	}
	
	public void deleteByIdAdptrCd(String adptrCd) {
		QAdapterTypePropertyId id = QAdapterTypeProperty.adapterTypeProperty.id;
		repository.deleteAll(repository.findAll(id.adptrCd.eq(adptrCd)));
	}

}
