package com.shkj.wms.scheduled;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class AllocationTasksUtils<k, V extends Number> {

    @Resource
    RedisTemplate redisTemplate;
    //传入的比例反转后的map
    private TreeMap<Double, String> weightMap = new TreeMap<>();
    //每次分配后map里面对应的value+1
    private Map<String, Double> map =new HashMap();
    //将出入的list里面所有的map存入
    private Map<String,Double> nmap =new HashMap();
    //复制传入比例反转后的map用于达到比例后的计算
    private TreeMap<Double,String> copyMap = new TreeMap<>();

    //出库时按比例分配所需的
    //传入的比例反转后的map
    private TreeMap<Double, String> outweightMap = new TreeMap<>();
    //每次分配后map里面对应的value+1
    private Map<String, Double> outmap =new HashMap();
    //将出入的list里面所有的map存入
    private Map<String,Double> outnmap =new HashMap();
    //复制传入比例反转后的map用于达到比例后的计算
    private TreeMap<Double,String> outcopyMap = new TreeMap<>();
    //添加或更新比例信息
    public void WeightRandomStrategy(List<Pair<String, Double>> list) {
        for (Pair<String, Double> pair : list) {
            nmap.put(pair.getKey(),pair.getValue());
            map.put(String.valueOf(pair.getKey()),0D);
            double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey();
            this.weightMap.put(pair.getValue().doubleValue() + lastWeight, pair.getKey());
        }

        //保存传入的值到redis
        redisTemplate.opsForValue().set("Distributor",nmap);
        redisTemplate.opsForValue().set("Distributor"+"nmap",nmap);
        redisTemplate.opsForValue().set("Distributor"+"weightMap",weightMap);
        redisTemplate.opsForValue().set("Distributor"+"map",map);
    }
    //添加或更新比例信息
    public void WeightRandomStrategyOut(List<Pair<String, Double>> list) {
        for (Pair<String, Double> pair : list) {
            outnmap.put(pair.getKey(),pair.getValue());
            outmap.put(String.valueOf(pair.getKey()),0D);
            double lastWeight = this.outweightMap.size() == 0 ? 0 : this.outweightMap.lastKey();
            this.outweightMap.put(pair.getValue().doubleValue() + lastWeight, pair.getKey());
        }

        //保存传入的值到redis
        redisTemplate.opsForValue().set("Distributorout",outnmap);
        redisTemplate.opsForValue().set("Distributorout"+"nmap",outnmap);
        redisTemplate.opsForValue().set("Distributorout"+"weightMap",outweightMap);
        redisTemplate.opsForValue().set("Distributorout"+"map",outmap);
    }

    public String randome(){
        if (redisTemplate.opsForValue().get("Distributor"+"weightMap")!=null){
            weightMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributor"+"weightMap");
        }
        copyMap.putAll(weightMap);
        redisTemplate.opsForValue().set("Distributor"+"copyMap",copyMap);
        String k = random();

        return k;
    }
    public String randomeout(){
        if (redisTemplate.opsForValue().get("Distributorout"+"weightMap")!=null){
            outweightMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributorout"+"weightMap");
        }
        outcopyMap.putAll(outweightMap);
        redisTemplate.opsForValue().set("Distributorout"+"copyMap",copyMap);
        String k = randomout();

        return k;
    }
    public String random() {

        Double aDouble = this.copyMap.lastKey();
        double random = Math.random();
        double randomWeight =  aDouble* random;
        SortedMap<Double, String> tailMap = this.copyMap.tailMap(randomWeight, false);
        String k = String.valueOf(this.copyMap.get(tailMap.firstKey()));
        if (redisTemplate.opsForValue().get("Distributor"+"copyMap")!=null){
            nmap= (Map) redisTemplate.opsForValue().get("Distributor");
        }
        BigDecimal o =  new BigDecimal(String.valueOf(nmap.get(k)));
        if (redisTemplate.opsForValue().get("Distributor"+"copyMap")!=null){
            map= (Map<String, Double>) redisTemplate.opsForValue().get("Distributor"+"map");
        }
        BigDecimal o2 = new BigDecimal(String.valueOf(map.get(k))) ;
        if (o.compareTo(o2)==0){
            System.out.println("========"+k);
            if (redisTemplate.opsForValue().get("Distributor"+"copyMap")!=null){
                copyMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributor"+"copyMap");
            }
            copyMap.remove(tailMap.firstKey());
            redisTemplate.opsForValue().set("Distributor"+"copyMap",copyMap);

            if (copyMap.size()==0){
                List collect = map.entrySet().stream().map(java.util.Map.Entry::getKey).collect(Collectors.toList());
                collect.stream().forEach(e->{
                    map.put(String.valueOf(e),0D);
                });
                redisTemplate.opsForValue().set("Distributor"+"map",map);
                if (redisTemplate.opsForValue().get("Distributor"+"weightMap")!=null){
                    weightMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributor"+"weightMap");
                }
                copyMap.putAll(weightMap);
            }
            k=random();
            return k;
        }
        Double o1 =  Double.valueOf(map.get(k));
        map.put(k,o1+1.0D);
        redisTemplate.opsForValue().set("Distributor"+"map",map);
        return k;
    }
    public String randomout() {

        Double aDouble = this.outcopyMap.lastKey();
        double random = Math.random();
        double randomWeight =  aDouble* random;
        SortedMap<Double, String> tailMap = this.outcopyMap.tailMap(randomWeight, false);
        String k = String.valueOf(this.outcopyMap.get(tailMap.firstKey()));
        if (redisTemplate.opsForValue().get("Distributorout"+"copyMap")!=null){
            outnmap= (Map) redisTemplate.opsForValue().get("Distributorout");
        }
        BigDecimal o =  new BigDecimal(String.valueOf(outnmap.get(k)));
        if (redisTemplate.opsForValue().get("Distributorout"+"copyMap")!=null){
            outmap= (Map<String, Double>) redisTemplate.opsForValue().get("Distributorout"+"map");
        }
        BigDecimal o2 = new BigDecimal(String.valueOf(outmap.get(k))) ;
        if (o.compareTo(o2)==0){
            System.out.println("========"+k);
            if (redisTemplate.opsForValue().get("Distributorout"+"copyMap")!=null){
                outcopyMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributorout"+"copyMap");
            }
            outcopyMap.remove(tailMap.firstKey());
            redisTemplate.opsForValue().set("Distributorout"+"copyMap",outcopyMap);

            if (outcopyMap.size()==0){
                List collect = outmap.entrySet().stream().map(java.util.Map.Entry::getKey).collect(Collectors.toList());
                collect.stream().forEach(e->{
                    outmap.put(String.valueOf(e),0D);
                });
                redisTemplate.opsForValue().set("Distributorout"+"map",outmap);
                if (redisTemplate.opsForValue().get("Distributorout"+"weightMap")!=null){
                    outweightMap= (TreeMap<Double, String>) redisTemplate.opsForValue().get("Distributorout"+"weightMap");
                }
                outcopyMap.putAll(outweightMap);
            }
            k=randomout();
            return k;
        }
        Double o1 =  Double.valueOf(outmap.get(k));
        outmap.put(k,o1+1.0D);
        redisTemplate.opsForValue().set("Distributorout"+"map",outmap);
        return k;
    }
}
