package com.fdkankan.scene.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fdkankan.common.constant.ErrorCode;
import com.fdkankan.common.constant.RecStatus;
import com.fdkankan.common.constant.RedisKey;
import com.fdkankan.common.constant.TbStatus;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.scene.entity.Scene3dNum;
import com.fdkankan.scene.mapper.IScene3dNumMapper;
import com.fdkankan.scene.service.IScene3dNumService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 八目场景编码表 服务实现类
 * </p>
 *
 * @author dengsixing
 * @since 2021-12-23
 */
@Slf4j
@Service
public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3dNum> implements IScene3dNumService {

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public List<String> findSceneNum() {
        return baseMapper.findSceneNum();
    }

    @Override
    public Scene3dNum findByNum(String sceneCode) {
        List<Scene3dNum> list = this.list(new QueryWrapper<Scene3dNum>()
                .eq("tb_status", TbStatus.VALID.code())
                .eq("rec_status", RecStatus.VALID.code())
                .eq("scene_code", sceneCode));
        if(CollUtil.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    @Override
    public void updateUsedStatus(List<String> nums) {
        baseMapper.updateUsedStatus(nums);
    }

    @Override
    public String generateSceneNum(){
        // 从缓存中获取
        String sceneNum = (String)redisTemplate.opsForList().leftPop(RedisKey.FDKANKAN_SCENE_NUMS);
        if(Objects.nonNull(sceneNum)){
            return sceneNum;
        }
        // 分布式加锁
        Long loading =  redisTemplate.opsForValue().increment(RedisKey.LOCK_FDKANKAN_SCENE_NUMS);
        if (loading.compareTo(1L) == 0) {
            try {
                log.info("开始从数据库加载场景码");
                List<String> nums = this.findSceneNum();
                this.updateUsedStatus(nums);
                redisTemplate.opsForList().rightPushAll(RedisKey.FDKANKAN_SCENE_NUMS, nums.toArray(new String[]{}));
                log.info("场景码加载完成");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                redisTemplate.opsForValue().decrement(RedisKey.LOCK_FDKANKAN_SCENE_NUMS);
            }
        }else{
            // 等待1秒加载缓存
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sceneNum = (String)redisTemplate.opsForList().leftPop(RedisKey.FDKANKAN_SCENE_NUMS);
        if(StrUtil.isEmpty(sceneNum)){
            log.error("场景码加载失败");
            throw new BusinessException(ErrorCode.FAILURE_CODE_5053);
        }
        return sceneNum;
    }

}
