package com.dxhy.erp.utils;

import com.dxhy.erp.dao.InvoiceSignDao;
import com.google.common.base.Objects;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName: SerialNoCache : 扫描流水号缓存
 * @author yuanlz
 * @date 2016年12月1日 下午11:05:55
 *
 */
@SuppressWarnings("AlibabaUndefineMagicConstant")
@Component
@Slf4j
public class SerialNoCache extends CacheLoader<String, String> {
    private static InvoiceSignDao dao;
    private static final LoadingCache<String, String> CACHE;

    static {
        // 有效期一天
        CACHE = CacheUtilBase.init(60 * 60 * 24, 1, new SerialNoCache());
    }

    @Override
    public String load(@NotNull String date) throws Exception {
        if (null == date || Objects.equal("", date)) {
            return null;
        }
        String maxSerialNo = SerialNoCache.dao.getMaxSerialNo();
        String maxDate = null;
        if (maxSerialNo != null) {
            maxDate = maxSerialNo.substring(0, 8);
        }
        if (null == maxSerialNo || maxSerialNo.length() < 7 || false == maxDate.equals(date)) {
            maxSerialNo = date + "0000000";
        }
        return maxSerialNo.substring(8);
    }

    public static String getNextSerialNo(String date) {
        try {
            Lock lock = new ReentrantLock(true);
            lock.tryLock(5, TimeUnit.SECONDS);
            String lastedSerialNo = CACHE.get(date);
            String newSerialNo = String.format("%07d", Long.parseLong(lastedSerialNo) + 1);
            CACHE.put(date, newSerialNo);
            return date + newSerialNo;
        } catch (ExecutionException e) {
            log.error("SerialNoCache:error " + date, e);
        } catch (InterruptedException e) {
            log.error("SerialNoCache:error lock", e);
        }
        return null;
    }

    @Autowired
    public void setDao(InvoiceSignDao dao) {
        SerialNoCache.dao = dao;
    }
}
