package io.renren.modules.snoop.service.impl;

import afu.org.checkerframework.checker.igj.qual.I;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.common.utils.ToEnglish;
import io.renren.modules.dataSet.service.DynamicSystemService;
import io.renren.modules.levelManage.entity.LevelEntity;
import io.renren.modules.snoop.dao.SnoopDao;
import io.renren.modules.snoop.entity.ColumnRuleEntity;
import io.renren.modules.snoop.entity.SnoopAndSnoopValueEntity;
import io.renren.modules.snoop.entity.SnoopEntity;
import io.renren.modules.snoop.entity.SnoopValueEntity;
import io.renren.modules.snoop.service.SnoopService;
import io.renren.modules.snoop.service.SnoopValueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("snoopService")
public class SnoopServiceImpl extends ServiceImpl<SnoopDao, SnoopEntity> implements SnoopService {

    @Resource
    private  SnoopDao snoopDao;
    @Autowired
    private DynamicSystemService dynamicSystemService;
    @Autowired
    private SnoopValueService snoopValueService;

    @Override
    public List<SnoopEntity> selectByName(Integer page, Integer size, String name) {
        if(page != null && size != null){
            page = (page - 1) * size;
        }

        return snoopDao.selectByName(page, size, name);
    }

    @Override
    public Integer getCountByName(String name) {
        return snoopDao.getCountByName(name);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SnoopEntity> page = this.page(
                new Query<SnoopEntity>().getPage(params),
                new QueryWrapper<SnoopEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void deleteBatch(Integer snoopIds) {
        // 删除snoop表中的部分
        this.removeByIds(Arrays.asList(snoopIds));

        // 删除snoop_value表中与snoop对应的部分
        QueryWrapper<SnoopValueEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("snoop_id", snoopIds);
        snoopValueService.remove(queryWrapper);

    }

    @Override
    public void saveMeasure(SnoopAndSnoopValueEntity snoopAndSnoopValueEntity) {

        // 保存snoopEntity
        SnoopEntity snoopEntity = new SnoopEntity();
        snoopEntity.setHbaseName(snoopAndSnoopValueEntity.getHbaseName());
        snoopEntity.setRemark(snoopAndSnoopValueEntity.getRemark());
        snoopEntity.setSnoopName(snoopAndSnoopValueEntity.getSnoopName());
        this.save(snoopEntity);

        // 得到Hbase表中数据 List<Map<String, String>>
        List<Map<String, String>> equmentAll = dynamicSystemService.getEqumentLimit(snoopEntity.getHbaseName(),100);

        // 根据每一个snoopValueEntity 计算出 每列的值
        for(ColumnRuleEntity columnRuleEntity : snoopAndSnoopValueEntity.getSnoopValueEntityList()){
            String measureType = columnRuleEntity.getMeasureType();
            String measureColumn = columnRuleEntity.getMeasureColumn();

            List<String> allVaules = new ArrayList<>();
            // 列名 ——> 拼音+after
            String pinYinmeasureColumn = ToEnglish.getPinYin(measureColumn);
            pinYinmeasureColumn += "_after";
            for(Map<String, String> item : equmentAll){
                allVaules.add(item.get(pinYinmeasureColumn));
            }

            // 进行计算
            String res = computerValues(allVaules, measureType);

            // 保存每一个snoopValueEntity
            SnoopValueEntity snoopValueEntity = new SnoopValueEntity();
            snoopValueEntity.setMeasureType(measureType);
            snoopValueEntity.setMeasureColumn(measureColumn);
            snoopValueEntity.setMeasureValue(res);
            snoopValueEntity.setSnoopId(snoopEntity.getId());
            snoopValueService.save(snoopValueEntity);
        }

    }

    private String computerValues(List<String> allVaules, String measureType) {

        String res = "";

        if(measureType.equals("Null Count")){
            res = getNull(allVaules);
        }else if(measureType.equals("Total Count")){
            res = getTotal(allVaules);
        }else if(measureType.equals("Maximum")){
            res = getMax(allVaules);
        }else if(measureType.equals("Minimum")){
            res = getMin(allVaules);
        }else if(measureType.equals("Average")){
            res = getAverage(allVaules);
        }else if(measureType.equals("Mode")){
            res = getMode(allVaules);
        }
        return res;
    }

    /**
     * 得到最大值
     * @param allVaules
     * @return
     */
    private String getMax(List<String> allVaules){
        Double max = Double.MIN_VALUE;
        List<Double> list = new ArrayList<>();
        for(String str : allVaules){
            try{
                if(str == "NULL"){
                    continue;
                }else{
                    double num = Double.parseDouble(str);
                    list.add(num);
                }

            }catch (Exception e){
                return "数据存在异常值，无法统计";
            }
        }
        for(Double item : list){
            if(item > max){
                max = item;
            }
        }
        return String.valueOf(max);
    }

    /**
     * 得到最小值
     * @param allVaules
     * @return
     */
    private String getMin(List<String> allVaules){
        Double min = Double.MAX_VALUE;
        List<Double> list = new ArrayList<>();
        for(String str : allVaules){
            try{
                if(str == "NULL"){
                    continue;
                }else{
                    double num = Double.parseDouble(str);
                    list.add(num);
                }

            }catch (Exception e){
                return "数据存在异常值，无法统计";
            }
        }
        for(Double item : list){
            if(item < min){
                min = item;
            }
        }
        return String.valueOf(min);
    }

    /**
     * 得到平均值
     * @param allVaules
     * @return
     */
    private String getAverage(List<String> allVaules){
        double sum = 0;
        List<Double> list = new ArrayList<>();
        for(String str : allVaules){
            try{
                if(str == "NULL"){
                    continue;
                }else {
                    double num = Double.parseDouble(str);
                    list.add(num);
                }
            }catch (Exception e){
                return "数据存在异常值，无法统计";
            }
        }
        for(Double item : list){
            sum += item;
        }
        sum = sum / (double) list.size();
        return String.valueOf(sum);

    }

    /**
     * 得到数据总数
     * @param allVaules
     * @return
     */
    private String getTotal(List<String> allVaules) {
        int size = allVaules.size();
        return String.valueOf(size);
    }

    /**
     * 得到空值数量
     * @param allVaules
     * @return
     */
    private String getNull(List<String> allVaules) {
        int countNull = 0;
        for(String str : allVaules){
            if(str.equals("NULL")){
                countNull++;
            }
        }
        return String.valueOf(countNull);
    }

    /**
     * 众数
     * @param allVaules
     * @return
     */
    private String getMode(List<String> allVaules){
        Map<String, Integer> countMap = new HashMap<>();

        // 计算每个字符串的出现次数
        for (String value : allVaules) {
            countMap.put(value, countMap.getOrDefault(value, 0) + 1);
        }

        // 找到出现次数最多的字符串
        String mode = null;
        int maxCount = 0;
        for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() > maxCount) {
                mode = entry.getKey();
                maxCount = entry.getValue();
            }
        }

        return mode;
    }
}
