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

import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
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.BoardTopicCategoryIndexDao;
import com.apobates.forum.core.entity.BoardTopicCategoryIndex;
import com.apobates.forum.core.entity.TopicCategory;

@Repository
public class BoardTopicCategoryIndexDaoImpl implements BoardTopicCategoryIndexDao {
	@PersistenceContext
	private EntityManager entityManager;
	@Value("${jpa.batch.size}")
	private int batchSize;

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int batchSave(List<BoardTopicCategoryIndex> entities) {
		int i = 0;
		for (BoardTopicCategoryIndex btc : entities) {
			entityManager.persist(btc);
			i++;
			if (i % batchSize == 0) {
				// Flush a batch of inserts and release memory.
				entityManager.flush();
				entityManager.clear();
			}
		}
		return i ;
	}

	@Override
	public Stream<BoardTopicCategoryIndex> findAllByBoard(long boardId, int boardGroupId) {
		return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.boardId = ?1 OR btc.volumesId = ?2", BoardTopicCategoryIndex.class).setParameter(1, boardId).setParameter(2, boardGroupId).getResultStream();
	}

	@Override
	public Stream<BoardTopicCategoryIndex> findAllByCategory(int categoryId) {
		return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.categoryId = ?1", BoardTopicCategoryIndex.class).setParameter(1, categoryId).getResultStream();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int delete(long boardId, Collection<Integer> categoryIdSet) {
		if(null == categoryIdSet || categoryIdSet.isEmpty()){
			return -1;
		}
		return entityManager.createQuery("DELETE FROM BoardTopicCategoryIndex btc WHERE btc.boardId = ?1 AND btc.categoryId IN ?2").setParameter(1, boardId).setParameter(2, categoryIdSet).executeUpdate();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Stream<TopicCategory> findAll(long boardId, int boardGroupId) {
		return entityManager.createNativeQuery("SELECT tc.* FROM apo_topic_category AS tc RIGHT OUTER JOIN apo_board_topic_category_index AS btc ON btc.CATEGORYID = tc.ID WHERE btc.CATEGORYID > ?1 AND ((btc.BOARDID = ?2) OR (btc.BOARDID = ?3 AND btc.VOLUMESID = ?4))", TopicCategory.class)
					.setParameter(1, 0)
					.setParameter(2, boardId)
					.setParameter(3, 0)
					.setParameter(4, boardGroupId)
					.getResultStream();
	}

	@Override
	public Stream<BoardTopicCategoryIndex> findAllByCategory(List<Integer> categoryIdList) {
		if(categoryIdList == null || categoryIdList.isEmpty()){
			return Stream.empty();
		}
		return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.categoryId IN ?1", BoardTopicCategoryIndex.class).setParameter(1, categoryIdList).getResultStream();
	}

}
