package com.gyee.runeconomy.service.WindDirection;



import com.gyee.runeconomy.dto.result.PowerPointData;
import com.gyee.runeconomy.model.auto.ProBasicEquipment;
import com.gyee.runeconomy.util.DateUtils;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 风向玫瑰图
 * 风向频次玫瑰图
 */
public class WindALG {

    /**
     * 风速风向玫瑰图
     * 风速：[0,2.5) [2.5,5) [5,7.5) [7.5,10) [10,12.5) [12.5,15) [15,17.5) [17.5,20) [20,22.5) [22.5,25) [25,inf)  11
     * @param list
     */
    public static Object fxRoses(List<PowerPointData> list){
        int[][] count = new int[11][16];

        list.stream().forEach(item -> {
            int fx = windFXAngle(item.getFx());
            int speed = windSpeed(item.getSpeed());
            if (speed < 11 && fx < 16)
                count[speed][fx] = 1;
        });

        return count;
    }
    /**
     * 风速风向玫瑰图-风速区域-映射
     * 风速：[0,3) [3,5) [5,10)  [10,12) [12,25) [25,inf)  6
     * @param list
     */
    public static Object fxysNewRoses(List<PowerPointData> list){
        int[][] count = new int[8][16];

        list.stream().forEach(item -> {
            int fx = windFXAngle(item.getFx());
            int speed = windNewSpeed(item.getSpeed());
            if (speed <= 8 && fx < 16)
                count[speed][fx] = 1;
        });
        return count;
    }
    /**
     * 风速风向玫瑰图-风速区域
     * 风速：[0,3) [3,5) [5,10)  [10,12) [12,25) [25,inf)  6
     * @param list
     */
    public static Object fxNewRoses(List<PowerPointData> list){

        double[][] count = new double[8][16]; // 存储风速值
        int[][] counts = new int[8][16]; // 记录每个位置的添加次数

        list.stream().forEach(item -> {
            int fx = windFXAngle(item.getFx()); // 获取风向索引
            int speed = windNewSpeed(item.getSpeed()); // 获取风速索引

            // 确保 speed 的值在有效范围内
            if (speed >= 0 && speed < 8 && fx >= 0 && fx < 16) {
                // 如果当前位置已经有数据，计算新的平均值
                if (counts[speed][fx] > 0) {
                    // 累加新的风速值
                    count[speed][fx] = Math.round((count[speed][fx] * counts[speed][fx] + item.getSpeed()) / (counts[speed][fx] + 1) * 100.0) / 100.0;
                } else {
                    // 第一次添加直接赋值并保留两位小数
                    count[speed][fx] = Math.round(item.getSpeed() * 100.0) / 100.0;
                }
                // 更新次数
                counts[speed][fx]++;
            }
        });



        return count;
    }

    public static Object speedtimeNewRoses(List<PowerPointData> list){
        double[] time1 = new double[7]; // 存储风时数（小时）

        // 按时间排序记录
        list.sort(Comparator.comparing(item -> item.getTime()));

        // 初始化上条时间变量
        String previousTime = ""; // 用来保存上一条记录的时间

        // 初始化上条时间变量
        String firstTime = "";  // 第一条数据的时间
        String lastTime = "";   // 最后一条数据的时间
        double totalInterval = 0.0; // 计算w文件中时间的间隔总和

        // 遍历数据
        for (int i = 0; i < list.size(); i++) {
            PowerPointData item = list.get(i);
            try {
                // 获取当前时间
                String currentTime = item.getTime();

                // 如果是第一条数据，记录第一条时间
                if (i == 0) {
                    firstTime = currentTime;
                }

                // 更新最后一条数据的时间
                if (i == list.size() - 1) {
                    lastTime = currentTime;
                }

                double interval = 0.0;
                if (!previousTime.isEmpty()) {
                    // 计算两个时间之间的间隔（单位：分钟）
                    interval = DateUtils.getTimeDiff(previousTime, currentTime);
                }

                // 更新上一条记录的时间
                previousTime = currentTime;

                // 计算总时间
                totalInterval += interval;

                if (item.getSpeed() < 3) {
                    time1[0] += interval;
                }
                if (item.getSpeed() >= 3.0 && item.getSpeed() < 5.0) {
                    time1[1] += interval;
                }
                if (item.getSpeed() >= 5.0 && item.getSpeed() < 7.0) {
                    time1[2] += interval;
                }
                if (item.getSpeed() >= 7.0 && item.getSpeed() < 9.0) {
                    time1[3] += interval;
                }
                if (item.getSpeed() >= 9.0 && item.getSpeed() < 11.0) {
                    time1[4] += interval;
                }
                if (item.getSpeed() >= 11.0 && item.getSpeed() < 20.0) {
                    time1[5] += interval;
                }
                if (item.getSpeed() >= 20.0 && item.getSpeed() <= 25.0) {
                    time1[6] += interval;
                }
            } catch (Exception e) {
                e.printStackTrace(); // 捕获并打印异常
            }
        }

        // 计算第一条和最后一条数据的间隔
        double firstLastInterval = 0.0;
        if (!firstTime.isEmpty() && !lastTime.isEmpty()) {
            firstLastInterval = DateUtils.getTimeDiff(firstTime, lastTime);
            firstLastInterval = firstLastInterval +10;
        }

        // 如果 time1 计算出来的总间隔不等于第一条和最后一条数据的间隔差异，调整 time1[0]
        if (Math.abs(totalInterval - firstLastInterval) > 0.0) {
            double difference = firstLastInterval - totalInterval;
            time1[0] += difference;  // 将差值添加到 time1[0]
        }
        int totalHours = 0;
        double jssj = firstLastInterval / 60;
        // 将 time1 的每个元素都除以 60，取整
        for (int i = 0; i < time1.length; i++) {
            time1[i] = Math.round(time1[i] / 60); // 四舍五入取整
            totalHours += time1[i];
        }
        if (totalHours != jssj){
            int diff = (int) (jssj - totalHours); // 计算差值
            // 调整第一个元素
            time1[0] += diff; // 根据差值调整第一个元素
            totalHours = (int) jssj; // 确保 totalHours 变为 jssj
        }
        return time1;
    }
    /**
     * 风向频次玫瑰图
     * 风速：[0,2.5) [2.5,5) [5,7.5) [7.5,10) [10,12.5) [12.5,15) [15,17.5) [17.5,20) [20,22.5) [22.5,25) [25,inf)  11
     * @param list
     */
    public static int[][] fxCountRoses(List<PowerPointData> list){
        int[][] count = new int[11][16];
        AtomicBoolean speedTag = new AtomicBoolean(false);
        AtomicInteger orispeed = new AtomicInteger();
        list.stream().sorted(Comparator.comparing(PowerPointData::getTime)).forEach(item -> {
            int fx = windFXAngle(item.getFx());
            int speed = windSpeed(item.getSpeed());

            if (!speedTag.get()) {

                speedTag.set(orispeed.equals(speed));
                orispeed.set(speed);
                if (speed < 11 && fx < 16)
                    count[speed][fx] ++;
            }

        });

        return count;
    }



    /**
     * 风向频次玫瑰图
     * 风速：[0,3) [3,5) [5,10)  [10,12) [12,25) [25,inf)  6
     * @param list
     */
    public static int[][] fxNewCountRoses(List<PowerPointData> list){
        int[][] count = new int[8][16];
        AtomicBoolean speedTag = new AtomicBoolean(false);
        AtomicInteger orispeed = new AtomicInteger();
        list.stream().sorted(Comparator.comparing(PowerPointData::getTime)).forEach(item -> {
            int fx = windFXAngle(item.getFx());
            int speed = windNewSpeed(item.getSpeed());

            if (!speedTag.get()) {

                speedTag.set(orispeed.equals(speed));
                orispeed.set(speed);
                if (speed <= 8 && fx < 16)
                    count[speed][fx] ++;
            }

        });

        return count;
    }


    /**
     * 风向频次雷达图
     * @param list
     * @return
     */
    public static int[] fxRadarRoses(List<PowerPointData> list,List<ProBasicEquipment> collect){

        try {
            int[] count = new int[16];
            list.stream().sorted(Comparator.comparing(PowerPointData::getSpeed)).forEach(item -> {
                int df = windDFAngle(item.getDfwc(),collect);
                if (count.length > df && count[df] < 1000) {
                    count[df]++;
                }
            });
            return count;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }


    /**
     * 静风频率计算 、平均风速计算
     * @param list  风速数组
     * @param cutInSpeed 切入风速
     * @return
     */
    public static List<Double> frequency(List<Double> list, double cutInSpeed){
        List<Double> result = new ArrayList<>();
        DecimalFormat df = new DecimalFormat("0.00");
        int count = 0;
        double speed = 0.0;
        for (Double fs : list){
            speed += fs;
            if (fs < cutInSpeed)
                count ++;
        }
        double frequency = list.size() > 0 ? Double.valueOf(df.format(((double)count / list.size() * 100 ))) : 0;
        double speedAVG = list.size() > 0 ? Double.valueOf(df.format(speed/list.size())) : 0;
        result.add(frequency);
        result.add(speedAVG);
        return result;
    }



    /**
     * 对风偏差分析图散点过滤  统计-50 到 50的
     * 频次
     * @param list
     *
     *
     * @return
     */
    public static List<Point> windDeviationScatter(List<PowerPointData> list,List<ProBasicEquipment> equipments){
        //正负偏差 [-50,-49,....,0,1,2,.....50]
        List<Point> ls = new ArrayList<>();
        LinkedHashSet<Double> keys = new LinkedHashSet<>();  //散点太多去重
        //次数统计
        for (int i = 0; i < list.size(); i++){
            PowerPointData item = list.get(i);
            double dfwc = 0;
//            if (equipments.size()>0) {
//                dfwc = Math.abs(item.getDfwc()) * 57.2958;//对风误差进行弧度转角度
//            } else {
                dfwc = Math.abs(item.getDfwc());
//            }
            int ele = (int)Math.round((item.getFx() + dfwc));
            int index = ele - 180;
            if (index >= -50 && index <= 50 && item.getSpeed() > 0) {
                double key = Math.abs(index) + item.getSpeed();
                if (!keys.contains(key))
                    ls.add(new Point(index, item.getSpeed()));
                keys.add(key);
            }
        }

        return ls;
    }


    /**
     * 静态偏航对风分析
     * 对风偏差散点过滤  统计-15 到 15的  正负偏差 [-15,-14,....,0,1,2,.....15]
     * 数据为二维数组 内层数组为3项. 第一项表示Y轴索引（风速）,  第二项代表X轴的索引（正负偏差） 第三项代表value值.
     * @param points
     * @return
     */
    public static Map<String, Object> windDeviationPoint(List<PowerPointData> points){
        try {
            List<PowerPointData> list = new ArrayList<>();
            List<Object> temp = new ArrayList<>();
            Map<String, Object> result = new HashMap<>();
            Map<Integer, double[]> map = new LinkedHashMap<>();

            //过滤对风偏差
            for (int i = 0; i < points.size(); i++){
                PowerPointData item = points.get(i);
                if ((item.getSpeed() < 4.5 || item.getSpeed() >= 10.5) && item.getMxzt() != 2)
                    continue;

                list.add(item);
                Integer speed = Math.toIntExact(Math.round(item.getSpeed()));
                if (!map.containsKey(speed))
                    map.put(speed, new double[2]);  //[0]最小值 [1]最大值

                double[] value = map.get(speed);
                double power = item.getPower() < 0 ? 0 : item.getPower();
                value[0] = power < value[0] ? power : value[0]; //最小值
                value[1] = power > value[1] ? power : value[1]; //最大值
            }

            int avg = 0;
            DecimalFormat sf = new DecimalFormat("0.00");
            for (int i = 0; i < list.size(); i++){
                PowerPointData item = list.get(i);
                Integer speed = Math.toIntExact(Math.round(item.getSpeed()));
//                int ele = (int) (Math.abs(item.getFx()) + Math.abs(item.getAngle()));
//                int ele = (int) (Math.abs(item.getFx()) + (Math.abs(item.getAngle()) - item.getFx()));//此处偏航角度为机舱位置
                int ele = (int) (Math.abs(item.getFx()));
                int index = ele - 180;
                if (index >= -30 && index <= 30 && item.getPower() > 0) {
                    avg += index;
                    double[] value = map.get(speed);
                    double v = (item.getPower() - value[0]) / (value[1] - value[0]);
                    double s[] = {speed, index, Double.valueOf(sf.format(v)).doubleValue()};
                    temp.add(s);
                }
            }
            result.put("data", temp);
            result.put("avg", temp.size() > 0 ? avg/temp.size() : 0);

            return result;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 对风偏差频次统计  统计-50 到 50
     * @param list
     * @return
     */
    public static int[] windDeviationRatio(List<PowerPointData> list,List<ProBasicEquipment> equipments){
        int[] pc = new int[101];  //正负偏差 [-50,-49,....,0,1,2,.....50]
        //次数统计
        List<Double> dfwcls = new ArrayList<>();
        List<Double> fxls = new ArrayList<>();
        for (int i = 0; i < list.size(); i++){
            PowerPointData item = list.get(i);
            double dfwc = 0;
//            if (equipments.size()>0) {
//                dfwc = Math.abs(item.getDfwc()) * 57.2958;
//                dfwcls.add(dfwc);
//            } else {
                dfwc = Math.abs(item.getDfwc());
                dfwcls.add(dfwc);
//            }
            fxls.add(item.getFx());
            int ele = (int) (Math.abs(item.getFx()) + dfwc);
            int index = ele - 180;
            if (index >= -50 && index <= 50)
                pc[50-(index > 0 ? -index : Math.abs(index))]++;
        }

        return pc;
    }

//    public static int[] windDeviationRatio(List<PowerPointData> list, List<ProBasicEquipment> equipments) {
//        int[] pc = new int[101];
//
//        for (int i = 0; i < list.size(); i++) {
//            PowerPointData item = list.get(i);
//            double fx = item.getFx();
//            double dfwc = 0;
//
//
//            fx = (fx + 360) % 360;
//
//
//            if (equipments.size() > 0) {
//                dfwc = Math.abs(item.getDfwc()) * 57.2958;
//            } else {
//                dfwc = Math.abs(item.getDfwc());
//            }
//
//
//            double ele = (fx + dfwc) % 360;
//
//
//            int index = (int) (ele - 180);
//
//
//            if (ele >= 130 && ele <= 230) {
//
//                int pcIndex = 50 + index;
//                if (pcIndex >= 0 && pcIndex <= 100) {
//                    pc[pcIndex]++;
//                }
//            }
//        }
//
//        return pc;
//    }
    /**
     * 风向划分
     * 0:0-22.5
     * 1:22.5-45
     * 2:90-135
     * .。。。。。。
     * @param fx
     * @return params: 0,1,2。。。。。15
     */
    private static int windFXAngle(double fx){
        int split = 16;  //风向分为16个角度
        double angle = (double)360 / split;
        int index = Math.abs((int) (fx / angle));
        return index;
    }

    /**
     * 对风角度计算
     * 0:0-22.5
     * 1:22.5-45
     * 2:90-135
     * .。。。。。。
     * @param
     * @return
     */
    private static int windDFAngle(double angle,List<ProBasicEquipment> collect){
        int split = 16;  //风向分为8个角度
        double dfwc =0;
        double interval = (double)360 / split;
        angle = angle > 360 ? 720 - 360 : angle;
        if (collect.size()>0){
            dfwc = Math.abs(angle) * 57.2958;
        } else {
            dfwc = Math.abs(angle);
        }

        int index = (int) (Math.abs(dfwc) / interval);
        return index;
    }

    /**
     * 风速区域划分
     * @param speed
     * @return
     */
    private static int windSpeed(double speed){
        if (speed < 2.5)
            return 0;
        else if (speed < 5)
            return 1;
        else if (speed < 7.5)
            return 2;
        else if (speed < 10)
            return 3;
        else if (speed < 12.5)
            return 4;
        else if (speed < 15)
            return 5;
        else if (speed < 17.5)
            return 6;
        else if (speed < 20)
            return 7;
        else if (speed < 22.5)
            return 8;
        else if (speed < 25)
            return 9;
        else
            return 10;
    }


    /**
     * 风速区域划分
     * @param speed
     * @return
     */
    private static int windNewSpeed(double speed){
        if (speed < 3)
            return 0;
        else if (3<= speed  && speed < 5)
            return 1;
        else if (5<= speed && speed < 7)
            return 2;
        else if (7<= speed && speed < 9)
            return 3;
        else if (9<= speed && speed < 11)
            return 4;
        else if (11<= speed && speed < 20)
            return 5;
        else if (20<= speed && speed < 25)
            return 6;
        else
            return 7;
    }

    /**
     * 数据聚合  间隔10
     * @param list
     * @return
     */
    private static Object arrayDistinct(List<List<Double>> list){
        for (List<Double> item : list){
            List<Double> lt = new ArrayList<>();
            LinkedHashSet<Integer> ls = new LinkedHashSet<>();
            item.forEach(ele -> {
                if (ele == null)
                    return;
                int v = (int) (ele / 10);
                if (!ls.contains(v))
                    lt.add(ele);

                ls.add(v);
            });
            item.clear();
            item.addAll(lt);
        }

        return list;
    }
}
