import com.codahale.metrics.MetricRegistry;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.niewj.datasource.utils.AlarmEvent;
import com.niewj.datasource.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
public class MonitorService {
    private Logger logger = LoggerFactory.getLogger(MonitorService.class);
    @Autowired
    private MetricRegistry metrics;
    private ExecutorService executor = Executors.newFixedThreadPool(3);
    private EventBus eventBus = new AsyncEventBus(executor);

    @PostConstruct
    public void init() {
        eventBus.register(this);
    }

    @PreDestroy
    public void destroy() {
        executor.shutdown();
    }

    public void post(AlarmEvent event) {
        if (event == null) return;
        if (event.type == null) return;
        if (StringUtil.isNullAndEmpty(event.key)) return;

        eventBus.post(event);
    }

    @Subscribe
    @AllowConcurrentEvents
    public void consume(AlarmEvent event) {
        try {
            switch (event.type) {
                case COUNT:
                    metrics.counter(event.key).inc(event.value);
                    logger.info("{} {}", event.key, event.value);
                    break;
                case METE:
                    metrics.meter(event.key).mark(event.value);
                    logger.info("{} {}", event.key, event.value);
                    break;
                case HISTOGRAM:
                    metrics.histogram(event.key).update(event.value);
                    logger.info("{} {}", event.key, event.value);
                    break;
                case TIME:
                    metrics.timer(event.key).update(event.value, TimeUnit.MILLISECONDS);
                    logger.info("{} {}", event.key, event.value);
                    break;
                default:
                    logger.error("*alarm event type no match,type={},key={}", event.type, event.key);
                    break;
            }
        } catch (Throwable e) {
        }
    }
}