package com.YuyeTech.HeartRate.game.levelInfo.service;

import com.YuyeTech.HeartRate.common.service.CommonServiceImpl;
import com.YuyeTech.HeartRate.dataobject.*;
import com.YuyeTech.HeartRate.dto.LevelJumpDTO;
import com.YuyeTech.HeartRate.game.levelInfo.projo.LevelCondition;
import com.YuyeTech.HeartRate.game.levelInfo.projo.LevelHonor;
import com.YuyeTech.HeartRate.game.levelInfo.projo.LevelJump;
import com.YuyeTech.HeartRate.game.levelInfo.repository.LevelConditionRepository;
import com.YuyeTech.HeartRate.game.levelInfo.repository.LevelHonorRepository;
import com.YuyeTech.HeartRate.game.levelInfo.repository.LevelJumpRepository;
import com.YuyeTech.HeartRate.game.levelInfo.vo.LevelJumpVo;
import com.YuyeTech.HeartRate.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * @author:slambb
 * @date:2021/8/4
 */
@Service
@Transactional
public class LevelJumpServiceImpl extends CommonServiceImpl<LevelJumpVo, LevelJump, Integer> implements LevelJumpService {

    @Autowired
    private LevelJumpRepository levelJumpRepository;
    @Autowired
    private LevelConditionRepository levelConditionRepository;
    @Autowired
    private LevelHonorRepository levelHonorRepository;

    @Autowired
    private UserLevelRepository userLevelRepository;

    @Override
    public List<LevelJump> findLevelJumpsByNumberTypeAndType(Integer numberType, Integer type, Sort.Direction direction) {
        return levelJumpRepository.findAllByNumberTypeAndType(numberType, type, Sort.by(direction, "sort"));
    }

    @Override
    public List<LevelJump> findLevelJumpsAll() {
        return levelJumpRepository.findAll();
    }

    @Override
    public List<LevelJumpDTO> findLevelJumpDTOsByNumberType(Integer numberType, Sort.Direction direction) {

        List<LevelJump> levelJumpList = levelJumpRepository.findAllByNumberTypeAndType(numberType, 1,Sort.by(direction, "sort"));
        List<LevelJumpDTO> levelJumpDTOList = levelJumpList.stream().map(
                e -> new LevelJumpDTO(
                        e.getId(),
                        e.getName(),
                        e.getDescribe(),
                        e.getRewardGold(),
                        e.getRewardDiamond(),
                        levelHonorRepository.findByType(e.getRewardHonor()).orElse(null),
                        e.getConsumeGold(),
                        e.getConsumeDiamond(),
                        e.getSignCount(),
                        e.getSignType(),
                        e.getLimitTime(),
                        levelConditionRepository.findByTypeAndLimitTypeIn(0, Pattern.compile(",").splitAsStream(e.getConditionUnlock()).map((x) -> Integer.parseInt(x))
                                .collect(Collectors.toList())),//解析关卡
                        levelConditionRepository.findByTypeAndLimitType(1, e.getConditionPassed()),
                        e.getExplain(),
                        e.getNumberType(),
                        false,
                        false,
                        1
                )
        ).collect(Collectors.toList());

        return levelJumpDTOList;
    }

    @Override
    public Map findLevelJumpsAll(String userId) {

        //关卡解锁数据读取，输出一个匹配的关卡数据
        UserLevel userLevel = userLevelRepository.findByUserIdAndEventType(userId, 1).orElse(null);
        List<Integer> unlockStateList = new ArrayList<>();
        List<Integer> passedStateList = new ArrayList<>();

        if (userLevel != null) {
            // 记录一个 id 数组。
            // 已经解锁的关卡id "0,1,2,3"
            unlockStateList = Pattern.compile(",").splitAsStream(userLevel.getUnlockState()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
            // 已经通过关卡的关卡id "0,1,2"
            passedStateList = Pattern.compile(",").splitAsStream(userLevel.getPassedState()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
        }

        List<LevelJump> levelJumpList = levelJumpRepository.findAll(Sort.by(Sort.Direction.ASC, "sort"));
        List<LevelJumpDTO> singlePerson = new ArrayList<>();
        List<LevelJumpDTO> multiPerson = new ArrayList<>();

        for (int i = 0; i < levelJumpList.size(); i++) {
            LevelJump e = levelJumpList.get(i);
            List<Integer> _limitTypes = Pattern.compile(",").splitAsStream(e.getConditionUnlock()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
            // 是否解锁,如果是 0 ，及存在自动解锁。
            Boolean _unlock = _limitTypes.contains(0);
            // 如果存在解锁关卡，并且不是1也是可以的
            Boolean _hasUnlock = unlockStateList.contains(e.getId());
            Boolean _isPassed = passedStateList.contains(e.getId());
            LevelJumpDTO _levelJumpDTO = new LevelJumpDTO(
                    e.getId(),
                    e.getName(),
                    e.getDescribe(),
                    e.getRewardGold(),
                    e.getRewardDiamond(),
                    levelHonorRepository.findByType(e.getRewardHonor()).orElse(null),
                    e.getConsumeGold(),
                    e.getConsumeDiamond(),
                    e.getSignCount(),
                    e.getSignType(),
                    e.getLimitTime(),
                    levelConditionRepository.findByTypeAndLimitTypeIn(0, _limitTypes),//解析关卡
                    levelConditionRepository.findByTypeAndLimitType(1, e.getConditionPassed()),
                    e.getExplain(),
                    e.getNumberType(),
                    _isPassed,
                    _unlock || _hasUnlock,
                    1
            );

            //单人，多人
            if (e.getNumberType().equals(1)) {
                singlePerson.add(_levelJumpDTO);
            } else if (e.getNumberType().equals(2)) {
                multiPerson.add(_levelJumpDTO);
            }
        }
        Map map = new HashMap();
        map.put("singlePerson", singlePerson);
        map.put("multiPerson", multiPerson);

        return map;
    }

    /**
     * 返回全部关卡和类型
     *
     * @param userId
     * @return
     */
    @Override
    public Map findLevels(String userId) {

        //关卡解锁数据读取，输出一个匹配的关卡数据
        List<UserLevel> userLevelList = userLevelRepository.findByUserId(userId);
        //当前是两组关卡来返回，1是跳，2是拳击
        List<LevelJump> levelJumpList = levelJumpRepository.findAll(Sort.by(Sort.Direction.ASC, "sort"));
        List<LevelJumpDTO> singlePerson = new ArrayList<>();
        List<LevelJumpDTO> multiPerson = new ArrayList<>();

        for (int i = 0; i < levelJumpList.size(); i++) {
            LevelJump e = levelJumpList.get(i);
            List<Integer> _limitTypes = Pattern.compile(",").splitAsStream(e.getConditionUnlock()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
            // 是否解锁,如果是 0 ，及存在自动解锁。
            Boolean _unlock = _limitTypes.contains(0);

            List<Integer> unlockStateList = new ArrayList<>();
            List<Integer> passedStateList = new ArrayList<>();
            for (int k = 0; k < userLevelList.size(); k++) {
                UserLevel userLevel = userLevelList.get(k);
                //根据记录关卡的type 和 当前关卡对应所属的type一样，
                if (userLevel.getEventType().equals(e.getType())) {
                    // 记录一个 id 数组。
                    // 已经解锁的关卡id "0,1,2,3"
                    unlockStateList = Pattern.compile(",").splitAsStream(userLevel.getUnlockState()).map((x) -> Integer.parseInt(x))
                            .collect(Collectors.toList());
                    // 已经通过关卡的关卡id "0,1,2"
                    passedStateList = Pattern.compile(",").splitAsStream(userLevel.getPassedState()).map((x) -> Integer.parseInt(x))
                            .collect(Collectors.toList());
                }
            }
            // 如果存在解锁关卡，并且不是1也是可以的
            Boolean _hasUnlock = unlockStateList.contains(e.getId());
            Boolean _isPassed = passedStateList.contains(e.getId());
            LevelJumpDTO _levelJumpDTO = new LevelJumpDTO(
                    e.getId(),
                    e.getName(),
                    e.getDescribe(),
                    e.getRewardGold(),
                    e.getRewardDiamond(),
                    levelHonorRepository.findByType(e.getRewardHonor()).orElse(null),
                    e.getConsumeGold(),
                    e.getConsumeDiamond(),
                    e.getSignCount(),
                    e.getSignType(),
                    e.getLimitTime(),
                    levelConditionRepository.findByTypeAndLimitTypeIn(0, _limitTypes),//解析关卡
                    levelConditionRepository.findByTypeAndLimitType(1, e.getConditionPassed()),
                    e.getExplain(),
                    e.getNumberType(),
                    _isPassed,
                    _unlock || _hasUnlock,
                    e.getType()
            );
            //单人，多人
            if (e.getNumberType().equals(1)) {
                singlePerson.add(_levelJumpDTO);
            } else if (e.getNumberType().equals(2)) {
                multiPerson.add(_levelJumpDTO);
            }
        }
        //根据type再分组
        Map<Integer, List<LevelJumpDTO>> singlePersonMap = singlePerson.stream().collect(Collectors.groupingBy(LevelJumpDTO::getLevelType));
        Map<Integer, List<LevelJumpDTO>> multiPersonMap = multiPerson.stream().collect(Collectors.groupingBy(LevelJumpDTO::getLevelType));
        Map map = new HashMap();
        map.put("singlePersonMap",singlePersonMap.values().stream().collect(Collectors.toList()));
        map.put("multiPersonMap",multiPersonMap.values().stream().collect(Collectors.toList()));
        return map;
    }

    @Override
    public LevelJump findById(Integer id) {
        return levelJumpRepository.findById(id).orElse(null);
    }


    @Override
    public List<LevelCondition> findAllLevelCondition() {

        return levelConditionRepository.findAll();
    }

    @Override
    public List<LevelHonor> findAllLevelHonor() {

        return levelHonorRepository.findAll();
    }
}
