package com.yutou.bilibili.BiliBili.Services.impl;

import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
import com.yutou.bilibili.Services.ISystemConfigService;
import com.yutou.bilibili.Tools.Config;
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveDataDao;
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveInfoDao;
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliUpInfoDao;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.*;
import com.yutou.bilibili.mybatis.dao.UBiliUpDao;
import com.yutou.bilibili.mybatis.model.UBiliUp;
import com.yutou.bilibili.mybatis.model.UBiliUpExample;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service("BiliBiliLiveService")
public class BiliBiliLiveServiceImpl implements IBiliBiliLiveService {
    @Resource
    BilibiliUpInfoDao upInfoDao;
    @Resource
    BilibiliLiveDataDao liveDataDao;
    @Resource
    BilibiliLiveInfoDao liveInfoDao;
    @Resource
    UBiliUpDao biliUpDao;
    @Resource
    ISystemConfigService configService;

    private <T> T getData(List<T> list) {
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public List<BilibiliUpInfo> getUpInfo() {
        return upInfoDao.selectByExample(new BilibiliUpInfoExample());
    }

    @Override
    public List<BilibiliUpInfo> getUpInfo(int uid, String power) {
        UBiliUpExample example = new UBiliUpExample();
        List<BilibiliUpInfo> upInfos = new ArrayList<>();
        if (power.equals("[-1]")) {
            upInfos = upInfoDao.selectByExample(new BilibiliUpInfoExample());
            return upInfos;
        }
        example.createCriteria().andUidEqualTo(uid);
        List<UBiliUp> list = biliUpDao.selectByExample(example);
        int[] ids = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            ids[i] = list.get(i).getRoomid();
        }
        if (list.isEmpty()) {
            return upInfos;
        }
        upInfos = upInfoDao.queryToRoomIds(ids);
        com.yutou.bilibili.Tools.Log.i("list = " + upInfos.size());
        return upInfos;
    }

    @Override
    public BilibiliUpInfo queryUp(BilibiliUpInfo data) {
        if (data.getRoomid() == null) {
            return null;
        }
        return queryUpToRoomId(data.getRoomid());
    }

    @Override
    public BilibiliUpInfo queryUpToUrl(String url) {
        BilibiliUpInfoExample example = new BilibiliUpInfoExample();
        example.createCriteria().andUrlEqualTo(url);
        return getData(upInfoDao.selectByExample(example));
    }

    @Override
    public BilibiliUpInfo queryUpToRoomId(int roomId) {
        BilibiliUpInfoExample example = new BilibiliUpInfoExample();
        example.createCriteria().andRoomidEqualTo(roomId);
        return getData(upInfoDao.selectByExample(example));
    }


    @Override
    public List<BilibiliLiveData> getLiveData() {
        return liveDataDao.selectByExample(new BilibiliLiveDataExample());
    }

    @Override
    public List<BilibiliLiveInfo> getLiveInfo() {
        return liveInfoDao.selectByExample(new BilibiliLiveInfoExample());
    }

    @Override
    public boolean addUpInfo(BilibiliUpInfo upData) {
        BilibiliUpInfoExample example = new BilibiliUpInfoExample();
        example.createCriteria().andRoomidEqualTo(upData.getRoomid());
        if (upInfoDao.selectByExample(example).isEmpty()) {
            return upInfoDao.insert(upData) > 0;
        } else {
            return false;
        }
    }

    @Override
    public boolean updateUpInfo(BilibiliUpInfo upData) {
        return upInfoDao.updateByPrimaryKey(upData) > 0;
    }

    @Override
    public boolean deleteUp(BilibiliUpInfo upData) {
        BilibiliUpInfoExample example = new BilibiliUpInfoExample();
        example.createCriteria().andRoomidEqualTo(upData.getRoomid());
        return upInfoDao.deleteByExample(example) > 0;
    }

    @Override
    public boolean addLiveData(BilibiliLiveData data) {
        if (!isLive()) {
            return false;
        }

        return liveDataDao.insert(data) > 0;
    }

    @Override
    public boolean addLiveInfo(BilibiliLiveInfo data) {
        if (!isLive()) {
            return false;
        }
        return liveInfoDao.insert(data) > 0;
    }

    @Override
    public List<BilibiliLiveData> queryLiveData(int roomId, Date startTime, Date endTime, String[] type) {
        return liveDataDao.queryLiveData(roomId, startTime, endTime, type);
    }

    @Override
    public int queryGiftSize(int roomId, int giftId, Date startTime, Date endTime) {
        int count = 0;
        for (BilibiliLiveData liveData : liveDataDao.queryTimeOfRoomid(roomId, giftId, startTime, endTime)) {
            count += liveData.getGiftindex() == null ? 0 : liveData.getGiftindex();
        }
        return count;
    }

    @Override
    public Map<String, Integer> queryGiftSize(int roomId, Date startTime, Date endTime) {
        Map<String, Integer> map = new HashMap<>();
        List<BilibiliLiveData> list = liveDataDao.queryTimeOfRoomid(roomId, -1, startTime, endTime);
        for (BilibiliLiveData liveData : list) {
            if (map.containsKey(liveData.getGiftname())) {
                map.put(liveData.getGiftname(), map.get(liveData.getGiftname()) + (liveData.getGiftindex() == null ? 0 : liveData.getGiftindex()));
            } else {
                map.put(liveData.getGiftname(), 1);
            }
        }
        return map;
    }

    @Override
    public int queryPriceSize(int roomId, Date startTime, Date endTime) {
        int count = 0;
        for (BilibiliLiveData liveData : liveDataDao.queryTimeOfRoomid(roomId, -1, startTime, endTime)) {
            count += liveData.getPrice() == null ? 0 : liveData.getPrice();
        }
        return count;
    }

    @Override
    public BilibiliLiveData queryGiftOfId(int giftId) {
        BilibiliLiveDataExample example = new BilibiliLiveDataExample();
        example.createCriteria().andGiftidEqualTo(giftId);
        List<BilibiliLiveData> list = liveDataDao.selectByExample(example);
        if (list.isEmpty()) {
            return null;
        } else {
            return list.get(0);
        }
    }

    @Override
    public int queryGiftUserToDistinct(BilibiliUpInfo upData, Date startTime, Date endTime, String[] type) {
        return liveDataDao.queryGiftUserToDistinct(upData.getRoomid(), -1, startTime, endTime, type);
    }

    @Override
    public int queryPopularCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
        int count = 0;
        for (BilibiliLiveInfo info : liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime)) {
            count += info.getPopular();
        }
        return count;
    }

    @Override
    public int queryUserCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
        int count = 0;
        for (BilibiliLiveInfo info : liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime)) {
            count += (info.getUserindex() + info.getVipuserindex());
        }
        return count;
    }

    @Override
    public Map<String, Integer> queryUserGiftCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
        Map<String, Integer> map = new HashMap<>();
        List<BilibiliLiveInfo> list = liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime);
        for (BilibiliLiveInfo info : list) {
            map.put(new SimpleDateFormat("HH").format(info.getSubtime()), info.getGiftuser() == null ? 0 : info.getGiftuser());
        }
        return map;
    }

    @Override
    public List<BilibiliLiveInfo> queryLiveInfo(BilibiliUpInfo upInfo, Date startTime, Date endTime) {
        return liveInfoDao.queryTimeOfRoomid(upInfo.getRoomid(), startTime, endTime);
    }

    @Override
    public List<Map<String, BigDecimal>> queryTimeGroup(int roomId, Date startTime, Date endTime) {
        return liveDataDao.queryPriceTimeGroup(roomId, startTime, endTime);
    }

    @Override
    public List<Map<String, BigDecimal>> queryGiftTimeGroup(int roomId, Date startTime, Date endTime) {
        return liveDataDao.queryGiftTimeGroup(roomId, startTime, endTime);
    }

    public boolean isLive() {
        String flag = configService.getConfig(Config.BILI_LIVE_FLAG);
        if (flag != null) {
            return !"0".equals(flag);
        }
        return true;
    }
}
