package com.bizzan.bitrade.service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.bizzan.bitrade.engine.ContractCoinMatchFactory;
import com.bizzan.bitrade.entity.CoinThumb;
import com.bizzan.bitrade.entity.KLine;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class KLineService {
	@Autowired
    private ContractMarketService contractMarketService;
	@Autowired
    private ContractCoinMatchFactory matchFactory;
	
	//private Map<String, Integer> periodMap = new HashMap<String, Integer>();
	public static String PERIOD[] = { "1min", "5min", "15min", "30min", "60min","4hour", "1day", "1mon", "1week" };
    private Map<String, Map<String, KLine>> kLineMap = new HashMap<>();
    private Map<String, CoinThumb> thumbMap = new HashMap<>();
	
	public void init() {
    	for(String symbol : this.matchFactory.getMatchMap().keySet()) {
    		Map<String, KLine> kPeriodMap = new HashMap<>();
    		kLineMap.put(symbol, kPeriodMap);
    		for(String period : PERIOD) {
    			KLine latest = contractMarketService.findLatest(symbol, period);
    			if(latest == null) {
    				latest = new KLine(period);
    				
    			}
    			kPeriodMap.put(period, latest);
    		}
    	}
    }
	
	private Map<String, BigDecimal> qMap = new HashMap<>();
	
	public void updateThumb(String symbol, CoinThumb thumb) {
		BigDecimal volume = BigDecimal.ZERO;
		if(qMap.containsKey(symbol))
			volume = thumb.getVolume().subtract(qMap.get(symbol));
		//if(symbol.equals("BTC/USDT"))
		//	log.info("volume1={}, volume2={}, diff={}", thumb.getVolume(), qMap.get(symbol), volume);

		qMap.put(symbol, BigDecimal.valueOf(thumb.getVolume().doubleValue()));
		
		
		if(volume.compareTo(BigDecimal.ZERO)<0) {
			thumb.setVolume(BigDecimal.ZERO);
		} else {
			thumb.setVolume(volume);
		}	
		thumbMap.put(symbol, thumb);
	}

	//@Scheduled(fixedRate = 1000)
	public void generateKLine() {
		for(String symbol: thumbMap.keySet()) {
			CoinThumb thumb = thumbMap.get(symbol);
	    	Map<String, KLine> periodMap = kLineMap.get(symbol);
	    	for(String period: periodMap.keySet()) {
	    		KLine kLine = periodMap.get(period);
	    		boolean save = false;
	    		long newTime = 0;
	    		if(!period.equals("1mon")) {
	    			int seconds = 1;
		    		if(period.equals("1min")) {
		    			seconds = 60;
		    		} else if (period.equals("5min")) {
		    			seconds = 300;
		    		} else if (period.equals("15min")) {
		    			seconds = 900;
		    		} else if (period.equals("30min")) {
		    			seconds = 1800;
		    		} else if (period.equals("60min")) {
		    			seconds = 3600;
		    		} else if (period.equals("4hour")) {
		    			seconds = 4*3600;
		    		} else if (period.equals("1day")) {
		    			seconds = 24*3600;
		    		} else if (period.equals("1week")) {
		    			seconds = 7*24*3600;
		    		}
		    		
		    		long count = (thumb.getTime() - kLine.getTime()) / seconds;
		    		if(count>=1) {
		    			save = true;
		    			newTime = kLine.getTime() + count * seconds;
		    			//contractMarketService.saveKLine(symbol, kLine);
		    		}
	    		} else {
	    			Calendar calendar1 = Calendar.getInstance();
	    			calendar1.setTimeInMillis(kLine.getTime()*1000);
	    			Calendar calendar2 = Calendar.getInstance();
	    			calendar2.setTimeInMillis(thumb.getTime()*1000);
	    			if(calendar1.get(Calendar.MONTH) != calendar2.get(Calendar.MONTH)) {
	    				save = true;
	    				int months = calendar2.get(Calendar.MONTH) - calendar1.get(Calendar.MONTH) + (calendar2.get(Calendar.YEAR) - calendar1.get(Calendar.YEAR))*12;
	    				calendar1.add(Calendar.MONTH, months);
	    				newTime = calendar1.getTimeInMillis() / 1000;
	    			}
	    		}
	    		
	    		if(kLine.getHighestPrice().compareTo(thumb.getClose())<0)
	    			kLine.setHighestPrice(thumb.getClose());
	    		if(kLine.getLowestPrice().compareTo(thumb.getClose())>0)
	    			kLine.setLowestPrice(thumb.getClose());
	    		kLine.setClosePrice(thumb.getClose());
	    		kLine.setVolume(kLine.getVolume().add(thumb.getVolume()));
	    		if(save) {
	    			//contractMarketService.saveKLine(symbol, kLine);
	    			
	    			kLine.setTime(newTime);
	    			kLine.setOpenPrice(thumb.getClose());
	    			kLine.setHighestPrice(thumb.getClose());
	    			kLine.setLowestPrice(thumb.getClose());
		    		kLine.setClosePrice(thumb.getClose());
		    		kLine.setVolume(BigDecimal.ZERO);
	    		}
	    	}
		}
    	
    }
    
    public KLine getKLine(String symbol, String period) {
        Map<String, KLine> periodMap = kLineMap.get(symbol);
        if (periodMap != null && periodMap.containsKey(period)) {
            return periodMap.get(period);
        }
        return contractMarketService.findLatest(symbol, period);
    }
}
