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

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.apobates.forum.attention.core.ImagePathCoverter;
import com.apobates.forum.core.api.ImageIOMeta;
import com.apobates.forum.core.api.dao.BoardCarouselIndexDao;
import com.apobates.forum.core.api.dao.BoardDao;
import com.apobates.forum.core.api.dao.BoardGroupDao;
import com.apobates.forum.core.api.dao.TopicCarouselDao;
import com.apobates.forum.core.api.dao.TopicCarouselSlideDao;
import com.apobates.forum.core.api.service.TopicCarouselService;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardCarouselIndex;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.TopicCarousel;
import com.apobates.forum.core.entity.TopicCarouselSlide;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.lang.TriFunction;

@Service
public class TopicCarouselServiceImpl implements TopicCarouselService{
	@Autowired
	private TopicCarouselDao topicCarouselDao;
	@Autowired
	private TopicCarouselSlideDao topicCarouselSlideDao;
	@Autowired
	private BoardCarouselIndexDao boardCarouselIndexDao;
	@Autowired
	private BoardGroupDao boardGroupDao;
	@Autowired
	private BoardDao boardDao;
	
	@Override
	public Stream<TopicCarousel> getAll() {
		return topicCarouselDao.findAll();
	}

	@Override
	public Optional<TopicCarousel> get(int id) {
		if(id>0){
			return topicCarouselDao.findOne(id);
		}
		return Optional.empty();
	}

	@Override
	public int create(String title, String summary, boolean status) throws IllegalStateException{
		TopicCarousel tc = new TopicCarousel(title,summary,status);
		try{
			topicCarouselDao.save(tc);
			if(tc.getId()<1) {
				throw new IllegalStateException("轮播图创建失败");
			}
		}catch(Exception e){
			throw new IllegalStateException(e.getMessage());
		}
		return tc.getId();
	}

	@Override
	public Optional<TopicCarousel> get(String title) {
		Function<Integer,Set<TopicCarouselSlide>> fun=(carouselId)->topicCarouselSlideDao.findAllUsed(carouselId).collect(Collectors.toSet());
		Optional<TopicCarousel> opt = topicCarouselDao.findOne(title);
		opt.ifPresent(tc->{
			tc.setSlides(fun.apply(tc.getId()));
		});
		return opt;
	}

	@Override
	public Optional<TopicCarousel> get(String title, ImageIOMeta imageIO) {
		Consumer<TopicCarouselSlide> action = tcs->{
			String imagePath =  new ImagePathCoverter(tcs.getImageAddr()).decodeUploadImageFilePath(imageIO.getImageBucketDomain(), imageIO.getUploadImageDirectName()).orElse("/static/img/140x140.png");
			tcs.setImageAddr(imagePath);
		};
		Function<Integer,Set<TopicCarouselSlide>> fun=(carouselId)->topicCarouselSlideDao.findAllUsed(carouselId).peek(action).collect(Collectors.toSet());
		Optional<TopicCarousel> opt = topicCarouselDao.findOne(title);
		opt.ifPresent(tc->{
			tc.setSlides(fun.apply(tc.getId()));
		});
		return opt;
	}

	@Override
	public Optional<Boolean> edit(int id, String title, String summary, boolean status)throws IllegalStateException {
		TopicCarousel tc = get(id).orElseThrow(()->new IllegalStateException("轮播图不存在或无法访问"));
		tc.setTitle(title);
		tc.setSummary(summary);
		tc.setStatus(status);
		return topicCarouselDao.edit(tc);
	}

	@Override
	public Optional<Boolean> remove(int id)throws IllegalStateException {
		return topicCarouselDao.editStatus(id, false);
	}

	@Override
	public Optional<Boolean> bindBoard(int boardGroupId, long boardId, int topicCarouselId, LocalDateTime expireDateTime)throws IllegalStateException {
		if(expireDateTime == null){
			throw new IllegalStateException("过期不可以为空");
		}
		if(boardGroupId <1 || topicCarouselId <1){
			throw new IllegalStateException("未知的版块组或轮播图");
		}
		BoardCarouselIndex bci = new BoardCarouselIndex();
		bci.setBoardId(boardId);
		bci.setVolumesId(boardGroupId);
		bci.setCarouselId(topicCarouselId);
		bci.setExpireDateTime(expireDateTime);
		bci.setEntryDateTime(LocalDateTime.now());
		try{
			boardCarouselIndexDao.save(bci);
			return Optional.of(true);
		}catch(Exception e){
			throw new IllegalStateException(e.getMessage());
		}
	}

	@Override
	public Optional<TopicCarousel> get(int boardGroupId, long boardId, ImageIOMeta imageIO) {
		Consumer<TopicCarouselSlide> action = tcs->{
			String imagePath =  new ImagePathCoverter(tcs.getImageAddr()).decodeUploadImageFilePath(imageIO.getImageBucketDomain(), imageIO.getUploadImageDirectName()).orElse("/static/img/140x140.png");
			tcs.setImageAddr(imagePath);
		};
		Function<Integer,Set<TopicCarouselSlide>> fun=(carouselId)->topicCarouselSlideDao.findAllUsed(carouselId).peek(action).collect(Collectors.toSet());
		
		Optional<TopicCarousel> opt = boardCarouselIndexDao.findOneByBoard(boardGroupId, boardId);
		opt.ifPresent(tc->{
			tc.setSlides(fun.apply(tc.getId()));
		});
		return opt;
	}

	@Override
	public Stream<BoardCarouselIndex> getAllRelative(int topicCarouselId) {
		List<BoardCarouselIndex> bcis = boardCarouselIndexDao.findAllByCarousel(topicCarouselId).collect(Collectors.toList());
		// 20200710
		final Map<Integer, Long> allQueryParam = Commons.collectMap(bcis.stream(), BoardCarouselIndex::getVolumesId, BoardCarouselIndex::getBoardId);
		final TriFunction<BoardGroup, Board, BoardCarouselIndex, BoardCarouselIndex> action = (bg, b, bci) -> {
			Optional<BoardCarouselIndex> opt = Optional.ofNullable(bci);
			if (null != b) {
				opt.ifPresent(tbci -> tbci.setBoard(b));
			}
			if (null != bg && bg.getId() > 0) {
				opt.ifPresent(tbci -> tbci.setVolumes(bg));
			}
			return opt.orElse(null);
		};
		CompletableFuture<Map<Long, Board>> boardMap = CompletableFuture.supplyAsync(() -> boardDao.findAllById(allQueryParam.values())).thenApply(boards -> boards.collect(Collectors.toMap(Board::getId, Function.identity())));
		CompletableFuture<Map<Integer, BoardGroup>> boardGroupMap = CompletableFuture.supplyAsync(() -> boardGroupDao.findAllById(allQueryParam.keySet())).thenApply(boardGroups -> boardGroups.collect(Collectors.toMap(BoardGroup::getId, Function.identity())));
		return boardMap.thenCombine(boardGroupMap, (bmap, bgmap) -> {
			return bcis.parallelStream().map(bci -> action.apply(bgmap.get(bci.getVolumesId()), bmap.get(bci.getBoardId()), bci)).filter(Objects::nonNull);
		}).join();
	}

	@Override
	public Optional<Boolean> remove(int topicCarouselId, int boardGroupId, long boardId)throws IllegalStateException {
		return boardCarouselIndexDao.deleteBoardCarouselIndex(topicCarouselId, boardGroupId, boardId);
	}

}
