package com.apobates.forum.core.impl.dao;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.apobates.forum.core.api.dao.TopicCarouselSlideDao;
import com.apobates.forum.core.entity.TopicCarouselSlide;

@Repository
public class TopicCarouselSlideDaoImpl implements TopicCarouselSlideDao{
	@PersistenceContext
	private EntityManager entityManager;
	@Value("${jpa.batch.size}")
	private int batchSize;
	private final static Logger logger = LoggerFactory.getLogger(TopicCarouselSlideDaoImpl.class);
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void save(TopicCarouselSlide entity) {
		entityManager.persist(entity);
	}

	@Override
	public Optional<TopicCarouselSlide> findOne(Integer primaryKey) {
		return Optional.ofNullable(entityManager.find(TopicCarouselSlide.class, primaryKey));
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> edit(TopicCarouselSlide updateEntity) {
		try {
			entityManager.merge(updateEntity);
			return Optional.of(true);
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}

	@Override
	public Stream<TopicCarouselSlide> findAll() {
		return Stream.empty();
	}

	@Override
	public long count() {
		return 0L;
	}

	@Override
	public Stream<TopicCarouselSlide> findAllUsed(int topicCarouselId) {
		return entityManager.createQuery("SELECT tcs FROM TopicCarouselSlide tcs WHERE tcs.status = ?1 AND tcs.topicCarouselId = ?2 ORDER BY tcs.ranking ASC", TopicCarouselSlide.class)
				.setParameter(1, true)
				.setParameter(2, topicCarouselId)
				.getResultStream();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Stream<TopicCarouselSlide> findAllUsed(String topicCarouselTitle) {
		final String SQL="SELECT tcs.* FROM apo_topic_carousel_slide tcs LEFT OUTER JOIN apo_topic_carousel tc ON tcs.TOPICCAROUSELID=tc.ID WHERE tcs.STATUS = ?1 AND tc.TITLE = ?2 ORDER BY tcs.RANKING ASC";
		return entityManager.createNativeQuery(SQL, TopicCarouselSlide.class).setParameter(1, "1").setParameter(2, topicCarouselTitle).getResultStream();
	}

	@Override
	public Stream<TopicCarouselSlide> findAll(int topicCarouselId) {
		return entityManager.createQuery("SELECT tcs FROM TopicCarouselSlide tcs WHERE tcs.topicCarouselId = ?1 ORDER BY tcs.ranking ASC", TopicCarouselSlide.class)
				.setParameter(1, topicCarouselId)
				.getResultStream();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> editRanking(int id, int ranking) {
		try{
			int affect = entityManager.createQuery("UPDATE TopicCarouselSlide tcs SET tcs.ranking = ?1 WHERE tcs.id = ?2").setParameter(1, ranking).setParameter(2, id).executeUpdate();
			return affect == 1?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int editRanking(Map<Integer, Integer> rankingMap) {
		if(rankingMap==null || rankingMap.isEmpty()){
			return -1;
		}
		
		int i = 0; 
		Query query = entityManager.createQuery("UPDATE TopicCarouselSlide tcs SET tcs.ranking = ?1 WHERE tcs.id = ?2");
		for (Entry<Integer, Integer> entry : rankingMap.entrySet()) {
			i += query.setParameter(1, entry.getValue()).setParameter(2, entry.getKey()).executeUpdate();
		}
		return i;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> editStatus(int id, int topicCarouselId, boolean status) {
		int affect = entityManager.createQuery("UPDATE TopicCarouselSlide tcs SET tcs.status = ?1 WHERE tcs.id = ?2 AND tcs.topicCarouselId = ?3")
				.setParameter(1, status)
				.setParameter(2, id)
				.setParameter(3, topicCarouselId)
				.executeUpdate();
		return affect == 1 ? Optional.of(true) : Optional.empty();
	}
}
