package com.sonic.lion.utils;

import com.sonic.common.exception.SysException;
import com.sonic.common.exception.SysExceptionUtils;
import org.apache.log4j.Logger;

import java.net.InetAddress;
import java.text.NumberFormat;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class AbstractKeyGenerator {
    private static final Logger LOGGER = Logger.getLogger(AbstractKeyGenerator.class);
    private static final int SEQ_MIN = 1;
    private static final int SEQ_MAX = 999;
    private static final int SEQ_DIGITS = 3;
    private static final AtomicInteger SEQ_ATOMIC_INTEGER = new AtomicInteger(1);
    private static final char IP_SPACER = '.';
    private static final String IP_AFTER_TWO;
    private static final int IP_DIGITS = 2;
    private static final int IP_MOD = 99;
    private static final String PATTERN = "yyyyMMddHHmmssSSS";
    private static final int ORDER_NO_MAX_SIZE = 29;

    public AbstractKeyGenerator() {
    }

    public String generatorUniqueKey(String businessCode) {
        StringBuffer buffer = new StringBuffer();
        String date = DateConvertUtils.getNow(PATTERN);
        buffer.append(this.customKey()).append(businessCode).append(date).append(IP_AFTER_TWO).append(formatNumber((long)getSeq(), SEQ_DIGITS));

        SysExceptionUtils.check(buffer.length() > ORDER_NO_MAX_SIZE,"", "tradeNo to long, tradeNo->" + buffer.toString());
        return buffer.toString();
    }

    public String generatorOrderKey(Boolean isShort) {
        StringBuffer buffer = new StringBuffer();
        return this.generatorOrderKey(isShort, buffer, "");
    }

    public String generatorOrderKey(Boolean isShort, String businessCode) {
        StringBuffer buffer = new StringBuffer();
        return this.generatorOrderKey(isShort, buffer, businessCode);
    }

    public String generatorOrderKey(Boolean isShort, String prefix, String businessCode) {
        StringBuffer buffer = new StringBuffer(prefix);
        return this.generatorOrderKey(isShort, buffer, businessCode);
    }

    public String generatorOrderKey(Boolean isShort, StringBuffer buffer, String businessCode) {
        String date = DateConvertUtils.getNow("yyyyMMdd");
        if (isShort) {
            date = DateConvertUtils.getNow("yyyyMMdd");
        }

        buffer.append(date).append(IP_AFTER_TWO).append(formatNumber((long)getSeq(), 8)).append(businessCode).append(this.customOrderKey());
        if (buffer.length() > 29) {
            throw new SysException("", "orderNo to long, orderNo->" + buffer.toString());
        } else {
            return buffer.toString();
        }
    }

    public abstract String customOrderKey();

    public abstract String customKey();

    private static int getSeq() {
        int result = SEQ_ATOMIC_INTEGER.incrementAndGet();
        if (result <= SEQ_MAX) {
            return result;
        } else {
            SEQ_ATOMIC_INTEGER.set(SEQ_MIN);
            return SEQ_MIN;
        }
    }

    private static String formatNumber(long number, int digits) {
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMaximumIntegerDigits(digits);
        nf.setMinimumIntegerDigits(digits);
        nf.setGroupingUsed(false);
        return nf.format(number);
    }

    static {
        String ip;
        try {
            InetAddress inetAddress = InetAddress.getLocalHost();
            ip = inetAddress.getHostAddress();
            ip = ip.substring(ip.lastIndexOf(46) + 1);
            ip = formatNumber(Long.valueOf(ip), IP_DIGITS);
        } catch (Exception var4) {
            LOGGER.error("can not get ip address", var4);
            Random random = new Random((long)UUID.randomUUID().toString().hashCode());
            int randomNum = random.nextInt(IP_MOD);
            ip = formatNumber((long)randomNum, IP_DIGITS);
        }

        IP_AFTER_TWO = ip;
    }
}
