package org.holer.server.util;

import org.holer.server.model.HolerData;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;


public class DataCollector {
    private static Map<Integer, DataCollector> collectors = new ConcurrentHashMap();
    private Integer port;
    private AtomicLong readBytes = new AtomicLong();
    private AtomicLong wroteBytes = new AtomicLong();
    private AtomicLong readMsgs = new AtomicLong();
    private AtomicLong wroteMsgs = new AtomicLong();
    private AtomicInteger channels = new AtomicInteger();

    public static DataCollector getCollector(Integer port) {
        DataCollector collector = (DataCollector) collectors.get(port);
        if (null == collector) {
            synchronized (collectors) {

                collector = (DataCollector) collectors.get(port);
                if (null == collector) {

                    collector = new DataCollector();
                    collector.setPort(port);
                    collectors.put(port, collector);
                }
            }
        }
        return collector;
    }

    public static List<HolerData> getInitAllData() {
        List<HolerData> allData = new ArrayList<>();
        Iterator<Map.Entry<Integer, DataCollector>> it = collectors.entrySet().iterator();
        while (it.hasNext()) {
            allData.add(((DataCollector) ((Map.Entry) it.next()).getValue()).getInitData());
        }
        return allData;
    }


    public static List<HolerData> getAllData() {
        List<HolerData> allData = new ArrayList<>();
        Iterator<Map.Entry<Integer, DataCollector>> it = collectors.entrySet().iterator();
        while (it.hasNext()) {
            allData.add(((DataCollector) ((Map.Entry) it.next()).getValue()).getData());
        }
        return allData;
    }


    public HolerData getInitData() {
        HolerData data = new HolerData();
        data.setChannels(this.channels.get());
        data.setPort(this.port);
        data.setReadBytes(this.readBytes.getAndSet(0L));
        data.setWroteBytes(this.wroteBytes.getAndSet(0L));
        data.setTimestamp(System.currentTimeMillis());
        data.setReadMsgs(this.readMsgs.getAndSet(0L));
        data.setWroteMsgs(this.wroteMsgs.getAndSet(0L));
        return data;
    }


    public HolerData getData() {
        HolerData data = new HolerData();
        data.setChannels(this.channels.get());
        data.setPort(this.port);
        data.setReadBytes(ServerUtil.divide(this.readBytes.get(), 1024L));
        data.setWroteBytes(ServerUtil.divide(this.wroteBytes.get(), 1024L));
        data.setTimestamp(System.currentTimeMillis());
        data.setReadMsgs(this.readMsgs.get());
        data.setWroteMsgs(this.wroteMsgs.get());
        return data;
    }


    public void incrementReadBytes(long bytes) {
        this.readBytes.addAndGet(bytes);
    }
    public void incrementWroteBytes(long bytes) {
        this.wroteBytes.addAndGet(bytes);
    }
    public void incrementReadMsgs(long msgs) {
        this.readMsgs.addAndGet(msgs);
    }
    public void incrementWroteMsgs(long msgs) {
        this.wroteMsgs.addAndGet(msgs);
    }
    public AtomicInteger getChannels() {
        return this.channels;
    }
    public Integer getPort() {
        return this.port;
    }
    public void setPort(Integer port) {
        this.port = port;
    }
}
