package link.at17.mid.tushare.data.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import link.at17.mid.tushare.data.models.StockInfo;
import link.at17.mid.tushare.data.models.StockValue;

public class PriceUtil {

    public static final BigDecimal DOT_05 = new BigDecimal("0.05");
    public static final BigDecimal DOT_1 = new BigDecimal("0.1");
    public static final BigDecimal DOT_2 = new BigDecimal("0.2");
    public static final BigDecimal TWO = new BigDecimal("2");
    
    /**
     * 根据股票信息获取涨跌幅限制<br/>
     * 股票以 30 或 68 为开头，或同花顺概念为注册制次新股的，返回 0.2<br/>
     * 不为以上情况，且为 ST 股票的，返回 0.05<br/>
     * 不为以上情况的，返回 0.1
     * @param stockInfo
     * @return
     */
    public static BigDecimal getLimitByStockInfo(StockInfo stockInfo) {
        if (stockInfo.getNudeCode().startsWith("30") 
                || stockInfo.getNudeCode().startsWith("68")
                || (stockInfo.getThsBelongings() != null && stockInfo.getThsBelongings().contains("注册制"))) {
            return new BigDecimal("0.2");
        }
        else if (stockInfo.getName().contains("ST")) {
            return new BigDecimal("0.05");
        }
        return new BigDecimal("0.1");
    }

    /**
     * 根据前收、现收和股票信息，判断股票是否涨停
     * @param preClose
     * @param nowClose
     * @param stockInfo
     * @return
     */
    public static boolean isLimit(double preClose, double nowClose, StockInfo stockInfo) {
        return isLimit(preClose, nowClose, stockInfo, false);
    }

    /**
     * 根据前收、现收和股票信息，判断股票是否涨/跌停
     * @param preClose
     * @param nowClose
     * @param stockInfo
     * @param negative 是否跌停
     * @return
     */
    public static boolean isLimit(double preClose, double nowClose, StockInfo stockInfo, boolean negative) {
        BigDecimal preCloseDec = new BigDecimal(preClose).setScale(2, RoundingMode.HALF_UP);
        BigDecimal nowCloseDec = new BigDecimal(nowClose).setScale(2, RoundingMode.HALF_UP);
        BigDecimal limit = getLimitByStockInfo(stockInfo);
        if (negative) {
            limit = limit.negate();
        }
        BigDecimal limitUp = preCloseDec.multiply(
                limit.add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP);
        boolean isLimitUp = limitUp.compareTo(nowCloseDec) == 0;
        if (limit.abs().compareTo(DOT_05) == 0) {
            limitUp = preCloseDec.multiply(
                    limit.multiply(TWO).add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP);
            isLimitUp = isLimitUp || limitUp.compareTo(nowCloseDec) == 0;
        }
        return isLimitUp;
    }
    /**
     * 判断是否达到涨跌幅限制
     * @param preClose 前收
     * @param nowClose 现收
     * @param upDownLimitPrecent 涨跌幅限制
     * @return
     */
    public static boolean isLimit(double preClose, double nowClose, BigDecimal upDownLimitPrecent) {
        BigDecimal preCloseDec = new BigDecimal(preClose).setScale(2, RoundingMode.HALF_UP);
        BigDecimal nowCloseDec = new BigDecimal(nowClose).setScale(2, RoundingMode.HALF_UP);
        BigDecimal limitUp = preCloseDec.multiply(
                upDownLimitPrecent.add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP);
        return limitUp.compareTo(nowCloseDec) == 0;
    }
    
    /**
     * 根据股价列表获取所有涨/跌停的 Indexes
     * @param stockValues 股价列表
     * @param upDownLimitPrecent 涨跌幅
     * @return
     */
    public static List<Integer> getLimitIndexes(List<? extends StockValue> stockValues, BigDecimal upDownLimitPrecent) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < stockValues.size() - 1; i++) {
            if (isLimit(stockValues.get(i).getClose(), stockValues.get(i + 1).getClose(), upDownLimitPrecent)) {
                list.add(i + 1);
            }
        }
        return list;
    }

}
