package quant.rich.emoney.protocol;

import java.util.function.Function;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * 支持的 ProtocolIDs<br/>
 * 见：sources\cn\emoney\acg\data\protocol\ProtocolIDs.java
 * 
 * @author Barry
 *
 */
public enum ProtocolID {

    DAILY_STRATEGY(9200), MARKET_CHANGES(9901),
    // MARKET_SITUATION(9000),
    OPERATION_POOL(9500), PRESELECTION_POOL(9600), SECTOR_LABEL(9100), STRATEGY_GROUP_POOL(9700, "StrategyStock"),
    STRATEGY_HEROES(9300), STRATEGY_MARK(9400), STRATEGY_SELECTION(9900),

    BLOCK_INDUSTRY_CHAIN(20800), BLOCK_STOCK_DESC(20700), BLOCK_STRONG_THEME(20900), THEME_BLOCK(2103),
    TIANJI_STOCK_HOLD(20600),

    GET_RECORD(4011), SET_RECORD(4311),

    BIG_ORDER(8200), BLOCK_ATTACK(8002), BLOCK_INDEX(9000), BLOCK_QZDJ(8003), CAPITAL_RADAR(8300),
    DAILY_OPPORTUNITY(8800), GROUP_DETAIL(9100), INDEX_INFLOW(8401), INDEX_TREND(8400), LIMIT_COMPARISON(8700),
    LONG_TERM_OPPORTUNITY(8801), SECTOR_ATTACK(8000), STOCK_PICKING(8100), TRADE_KALENDAR(8501), UPDOWN_STATISTIC(8600),
    UPDOWN_STATISTIC_DATE(8602), UPDOWN_STATISTIC_PACK(8601, "UpsAndDownsStatistics"),

    FUNDS_DX(2101),

    HAOGU_CARD_SUMMARY(5001), HAOGU_TYPE_CHARGE(5100), HAOGU_TYPE_NORMAL(5000), HAOGU_TYPE_REASON(5300),
    HAOGU_TYPE_SIMPLE(5200), HAOGU_TYPE_SIMPLE_2(5400), HAOGU_UPDATE_SUMMARY(5500),

    MIXHOME_BK_AND_ZJ(10000), MIXHOME_BK_AND_ZJ_EX(10001), MIXHOME_INDEX_CHART(10100), NET_FLOW_PREVIEW(10200),

    MS_BALANCE_AND_INDEX_TREND(20200), MS_RANK_DETAIL(20300), MS_RANK_LIST(20400), MS_VALID_DATE(20000),

    TREND_LINE_KCB(2303),

    BARGAIN_DATA(3100), BUYING_SELLING(3000), BUYING_SELLING_HIS(3002), BUYING_SELLING_LEV2(3001), CANDLE_STICK(2420),
    CANDLE_STICK_V2(2421), CANDLE_STICK_V3(2422, "CandleStickWithIndex"), CODE_LIST_UPDATE(2001, "CodeListUpdate"),
    GLOBAL_LIST(2700),
    // GoodsTable(2000),
    HGT_AMOUNT(2800), HGT_AMOUNT_HISTORY_TREND(2802), HGT_AMOUNT_TREND(2801), HGT_HISTORY_TURNOVER(2804),
    HGT_INSTITUTIONAL_SHARE_HOLDING(5607), HGT_INSTITUTIONAL_TRENDS(5606), HGT_TOP_BUY(5601), HGT_TOP_CONCEPT(5605),
    HGT_TOP_INDUSTRY(5604), HGT_TOP_SELL(5602), HGT_TOP_SHARE(5603), HGT_TOP_TEN(5600), HGT_TREND_TURNOVER(2805),
    INDEX_CALC(2920), INDEX_CALC_V2(2921, "IndexCalc"), MATRIXDATA(2500), NET_INFLOW(3200), NET_INFLOW_V2(3201),
    QUOTE_TICK_DETAIL(3700), RANK_LIST(2600),

    SORT_LIST(2100, "SortedList", (ObjectNode jo) -> {
        if (jo.has("requestTypeCase")) {
            int requestTypeCase = jo.get("requestTypeCase").asInt();
            /*
             * 1 - system 2 - custom 3 - goods 4 - group
             */
            if (requestTypeCase == 1) {
                // jo.remove("system");
                jo.remove("custom");
                jo.remove("goods");
                jo.remove("group");
            } else if (requestTypeCase == 2) {
                jo.remove("system");
                // jo.remove("custom");
                jo.remove("goods");
                jo.remove("group");
            } else if (requestTypeCase == 3) {
                jo.remove("system");
                jo.remove("custom");
                // jo.remove("goods");
                jo.remove("group");
            } else if (requestTypeCase == 4) {
                jo.remove("system");
                jo.remove("custom");
                jo.remove("goods");
                // jo.remove("group");
            }
        }
        return jo;
    }),

    THEME_FUND(2102), TIME_STATUS(3300), TREND_BASIS(3600), TREND_INDEX(3400), TREND_LINE(2300),
    TREND_LINE_EXTEND(2302), TREND_LINE_FS_HISTORY(2305), TREND_LINE_FS_OUTER(2306), TREND_LINE_FS_SIMPLE(2304),
    TREND_LINE_WITH_TRANSATION(2301), VALUE_DATA(2200),

    OPTIONAL_GET_CLOUD(4001, "GetGroupGoods"), OPTIONAL_GET_GROUP(4010), OPTIONAL_GROUP_GET(4110, "GetGoodsGroup"),
    OPTIONAL_GROUP_SET(4210), OPTIONAL_SET(4310),

    GET_MERGE_CODE_LIST(3900), GUESS(4400), SET_MERGE_CODE_LIST(3800),

    GET_ALARM(4601), SET_ALARM(4501),

    GET_ALL_GOODS_RECORD(4901), GET_FIRST_GOODS_RECORD(4902), GET_GOODS_RECORD(4701), SET_GOODS_RECORD(4801),

    SHORT_ALARMS(10301),

    CANCEL_ENTRUST(6400), QRY_BUSINESS(6700, "Business"), QRY_ENTRUST(6600), QUERY_STOCK_OPERABLE_LIMITS(6300),
    SIMULATE_ACCOUNT(5900, "VTradeAccount"), SIMULATE_ACCOUNT_DETAIL(6000), SIMULATE_BANK_DETAIL(6800),
    SIMULATE_HIS_YIELD(6100), SIMULATE_ORDER_ENTRUST(6200), SIMULATE_POSITIONS(6500), SIMULATE_RESET_ACC(5901),
    SIMULATE_RESET_RECODE(5902), SIMULATE_TRADE_STAT(6701), SIMULATE_TRANSFER(6900), SIMULATE_TRANSFER_FLOW(5800),

    MOTIF_GROUP_CONSTITUENT_STOCK(7300), MOTIF_GROUP_CREATOR_DETAIL(7500), MOTIF_GROUP_DETAIL(7100),
    MOTIF_GROUP_EXCHANGE_RECORD(7400), MOTIF_GROUP_FOLLOW(7600), MOTIF_GROUP_INCOME_TREND(7200), MOTIF_GROUP_LIST(7000),
    MOTIF_GROUP_PRAISE(7700);

    private Integer protocolId;
    private String requestClassPrefix = null;
    private Function<ObjectNode, ObjectNode> beforeDeserialize = null;

    public Integer getProtocolId() {
        return protocolId;
    }

    private ProtocolID(int protocolId) {
        this.protocolId = protocolId;
        String[] nameParts = this.name().toLowerCase().split("_");
        StringBuilder sb = new StringBuilder();
        for (String namePart : nameParts) {
            sb.append(firstToUpper(namePart));
        }
        requestClassPrefix = sb.toString();
    }

    private ProtocolID(int protocolId, String requestClassPrefix) {
        this.protocolId = protocolId;
        this.requestClassPrefix = requestClassPrefix;
    }

    private ProtocolID(int protocolId, String requestClassPrefix, Function<ObjectNode, ObjectNode> beforeDeserialize) {
        this(protocolId, requestClassPrefix);
        this.beforeDeserialize = beforeDeserialize;
    }

    public static ProtocolID fromValue(int protocolId) {
        for (ProtocolID p : ProtocolID.values()) {
            if (p.getProtocolId() == protocolId) {
                return p;
            }
        }
        return null;
    }

    public String toRequestClassName() {

        String requestOrResponse = "Request";
        StringBuilder finalSb = new StringBuilder("nano.");
        finalSb.append(requestClassPrefix).append(requestOrResponse).append("$").append(requestClassPrefix).append("_")
                .append(requestOrResponse);
        ;

        return finalSb.toString();
    }

    /**
     * 序列化之前清洗
     * 
     * @param jo
     * @return
     */
    public JsonNode beforeDeserialization(ObjectNode jo) {
        if (beforeDeserialize == null)
            return jo;
        return beforeDeserialize.apply(jo);
    }

    private static String firstToUpper(String s) {
        if (StringUtils.isNotEmpty(s)) {
            char[] cs = s.toCharArray();
            if (cs[0] >= 'a' && cs[0] <= 'z') {
                cs[0] -= 32;
            }
            return String.valueOf(cs);
        }
        return s;
    }
}
