package cn.com.qmth.stmms.ms.commons.constant;

import cn.com.qmth.stmms.ms.commons.threadPool.MyThreadPool;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

/**
 * @Description: 仲裁自动打回算法
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2019/11/6
 */
@Component
public class ArbitrateCallback {
    private static Logger LOGGER = LoggerFactory.getLogger(ArbitrateCallback.class);

    public int MAX_DISTANCE = 2 //仲裁档位
            , SUM_DISTANCE = 2 * 2 + 1;//最大落差档位和

    @Autowired
    MyThreadPool myThreadPool;

    /**
     * 自动打回算法
     *
     * @param levelsMap
     * @param maxDistance
     * @return
     */
    public void judge(Map<Long, String> levelsMap, int maxDistance, ArbitrateResult ar) {
        myThreadPool.arbitratePoolTaskExecutor.submit(new Callable<List<Distance>>() {

            @Override
            public List<Distance> call() throws Exception {
                MAX_DISTANCE = maxDistance;
                SUM_DISTANCE = MAX_DISTANCE * 2 + 1;
                List<Distance> result = judge(levelsMap, ar);
                if (Objects.nonNull(result)) {
                    LOGGER.info("LEVELS:{},设置的隔档档位为:{},设置的最大落差值和为:{},需要打回的档位为:{}", levelsMap.values().stream().collect(Collectors.toList()), MAX_DISTANCE, SUM_DISTANCE, JSONObject.toJSONString(result));
                }
                ar.callback(result);
                return result;
            }
        });
    }

    /**
     * 计算档位偏差值
     *
     * @param levelsMap
     * @param paperLevel
     * @param ar
     * @return
     */
//    @Async
    public void judge(Map<Long, String> levelsMap, String paperLevel, ArbitrateResult ar) {
        myThreadPool.arbitratePoolTaskExecutor.submit(new Callable<List<Distance>>() {

            @Override
            public List<Distance> call() throws Exception {
                List<Distance> result = new ArrayList<>();
                char p = paperLevel.charAt(0);
                levelsMap.forEach((k, v) -> {
                    char c = v.charAt(0);
                    Distance d = new Distance(c, k);
                    d.distance = Math.abs(c - p);
                    d.deviation = c -p;
                    result.add(d);
                    LOGGER.info("计算档位偏差值:{}", JSONObject.toJSONString(d));
                });
                if (Objects.nonNull(result)) {
                    LOGGER.info("LEVELS:{},paperLevel为:{},档位落差为:{}", levelsMap.values().stream().collect(Collectors.toList()), paperLevel, JSONObject.toJSONString(result));
                }
                ar.callback(result);
                return result;
            }
        });
    }

    /**
     * 计算档位最大落差档位和档位和
     *
     * @param levelsMap
     * @param ar
     * @return
     */
    public List<Distance> judge(Map<Long, String> levelsMap, ArbitrateResult ar) {
        List<Distance> result = new ArrayList<>();
        levelsMap.forEach((k, v) -> {
            char c = v.charAt(0);
            Distance d = new Distance(c, k);
            levelsMap.forEach((k1, v1) -> {
                char other = v1.charAt(0);
                int distance = Math.abs(c - other);
                d.max = Math.max(d.max, distance);
                d.sum += distance;
            });
            if (d.max >= MAX_DISTANCE && d.sum >= SUM_DISTANCE) {
                result.add(d);
            }
            LOGGER.info("计算档位最大落差档位和档位和:{}", JSONObject.toJSONString(d));
        });
        return result;
    }

    /**
     * 档位计算类[档位，最大档位落差，最大档位落差和，档位偏差值]
     */
    public class Distance {
        char c;
        int max;
        int sum;
        int distance;
        int deviation;
        Long markId;

        public Distance(char c, Long markId) {
            this.c = c;
            this.max = 0;
            this.sum = 0;
            this.distance = 0;
            this.deviation = 0;
            this.markId = markId;
        }

        public char getC() {
            return c;
        }

        public void setC(char c) {
            this.c = c;
        }

        public int getMax() {
            return max;
        }

        public void setMax(int max) {
            this.max = max;
        }

        public int getSum() {
            return sum;
        }

        public void setSum(int sum) {
            this.sum = sum;
        }

        public int getDistance() {
            return distance;
        }

        public void setDistance(int distance) {
            this.distance = distance;
        }

        public Long getMarkId() {
            return markId;
        }

        public void setMarkId(Long markId) {
            this.markId = markId;
        }

        public int getDeviation() {
            return deviation;
        }

        public void setDeviation(int deviation) {
            this.deviation = deviation;
        }
    }
}
