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

import java.util.Optional;
import java.util.Set;
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.decorater.ForumEncoder;
import com.apobates.forum.letterbox.api.dao.ForumLetterDao;
import com.apobates.forum.letterbox.api.dao.OutboxDao;
import com.apobates.forum.letterbox.api.service.ForumLetterService;
import com.apobates.forum.letterbox.entity.ForumLetter;
import com.apobates.forum.letterbox.entity.ForumLetterReceiver;
import com.apobates.forum.letterbox.entity.ForumLetterTypeEnum;
import com.apobates.forum.letterbox.entity.Outbox;
import com.apobates.forum.letterbox.impl.event.ForumLetterEventPublisher;
import com.apobates.forum.letterbox.impl.event.ForumLetterPostEvent;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.Pageable;

@Service
public class ForumLetterServiceImpl implements ForumLetterService{
	@Autowired
	private ForumLetterDao forumLetterDao;
	@Autowired
	private OutboxDao outboxDao;
	@Autowired
	private ForumLetterEventPublisher forumLetterEventPublisher;
	
	@Override
	public Optional<ForumLetter> get(long id) {
		return forumLetterDao.findOne(id);
	}

	@Override
	public long create(
			String title, 
			String content, 
			long receiver, 
			String receiverNickname, 
			long sender,
			String senderNickname)throws IllegalStateException {
		return build(title, content,receiver,receiverNickname,sender,senderNickname).map(ForumLetter::getId).orElse(0L);
	}

	@Override
	public long create(
			ForumLetterTypeEnum label, 
			String title, 
			String content, 
			long receiver,
			String receiverNickname, 
			long sender, 
			String senderNickname)throws IllegalStateException {
		if(receiver <= 0){
			return create(title, content, sender, senderNickname);
		}
		ForumLetter fl = new ForumLetter(title, Commons.htmlPurifier(content), sender, senderNickname, label);
		fl.getReceivers().add(new ForumLetterReceiver(receiver,receiverNickname));
		return create(fl).map(ForumLetter::getId).orElse(0L);
	}

	@Override
	public long create(String title, String content, long sender, String senderNickname)throws IllegalStateException {
		ForumLetter fl = new ForumLetter(title, Commons.htmlPurifier(content), sender, senderNickname, ForumLetterTypeEnum.CLAIM);
		return create(fl).map(ForumLetter::getId).orElse(0L);
	}

	@Override
	public Optional<ForumLetter> build(
			String title, 
			String content, 
			long receiver, 
			String receiverNickname, 
			long sender,
			String senderNickname)throws IllegalStateException {
		ForumLetter fl = new ForumLetter(title, Commons.htmlPurifier(content), sender, senderNickname, ForumLetterTypeEnum.LETTER);
		fl.getReceivers().add(new ForumLetterReceiver(receiver, receiverNickname));
		return create(fl);
	}

	@Override
	public Optional<ForumLetter> getOneLazyReceiver(long id) {
		Optional<ForumLetter> fl = get(id);
		if(!fl.isPresent()){
			return Optional.empty();
		}
		Set<ForumLetterReceiver> res = outboxDao.findAllByLetter(id).map(r -> new ForumLetterReceiver(r.getReceiver(), r.getReceiverNickname())).collect(Collectors.toSet());
		fl.get().setReceivers(res);
		return fl;
	}

	@Override
	public Optional<ForumLetter> create(ForumLetter letter)throws IllegalStateException {
		long id = 0L;
		try{
			//无HTML tag,Emoji安全
			final String encodeLetterContent = new ForumEncoder(letter.getContent()).parseEmoji().getContent(); //.noneHtmlTag()
			final String encodeLetterTitle = new ForumEncoder(letter.getTitle()).noneHtmlTag().parseEmoji().getContent();
			letter.setContent(encodeLetterContent);
			letter.setTitle(encodeLetterTitle);
			//
			forumLetterDao.save(letter);
			id = letter.getId();
		}catch(Exception e){}
		if(id==0){
			throw new  IllegalStateException("信件创建失败");
		}
		if(!letter.getReceivers().isEmpty()){
			final long letterId = id;
			Set<Outbox> letterSendRecords = letter.getReceivers().stream().map(rc -> new Outbox(letter.getAuthor(), rc.getMember(), rc.getMemberNickname(), letterId)).collect(Collectors.toSet());
			outboxDao.batchSave(letterSendRecords);
		}
		forumLetterEventPublisher.publishPostsEvent(new ForumLetterPostEvent(this, letter));
		return Optional.of(letter);
	}

	@Override
	public Stream<ForumLetter> getMutualLetter(long sender, long receiver) {
		return forumLetterDao.findAll(sender, receiver);
	}

	@Override
	public Page<ForumLetter> getMutualLetter(long sender, long receiver, Pageable pageable) {
		return forumLetterDao.findAll(sender, receiver, pageable);
	}

	@Override
	public Stream<ForumLetter> getTodayClaim() {
		return forumLetterDao.getTodayClaim();
	}
}
