package com.tsi.comm.server.process.logging;

import com.tsi.app.common.app.AppUtils;
import com.tsi.comm.server.config.TsiCvimServerConfig;
import com.tsi.comm.server.process.AbstractTsiCvimProcess;
import com.tsi.comm.server.process.AbstractTsiCvimWorker;
import com.tsi.comm.server.protocol.AbstractTsiPacket;
import com.tsi.comm.server.repository.TsiNodeManager;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Getter
@Service
public class TsiCvimLoggingProcess extends AbstractTsiCvimProcess {

    private List<TsiCvimLoggingWorker> workerList = new ArrayList<TsiCvimLoggingWorker>();

    @PostConstruct
    void init() {
        ThreadGroup workerGroup = new ThreadGroup("loggingProcess");
        TsiCvimServerConfig tsiCvimServerConfig = (TsiCvimServerConfig) AppUtils.getBean(TsiCvimServerConfig.class);

        this.workers = tsiCvimServerConfig.getLoggingWorkers();
        if (this.workers <= 0) this.workers = 1;
        int nodes = TsiNodeManager.getInstance().size();
        int qSize = tsiCvimServerConfig.getQueueSize();
        if (nodes > qSize) {
            qSize = nodes;
        }
        qSize *= 6;
        qSize /= this.workers;
        for (int ii = 0; ii < this.workers; ii++) {
            TsiCvimLoggingWorker loggingWorker = new TsiCvimLoggingWorker(ii, qSize);
            this.workerList.add(loggingWorker);
            Thread worker = new Thread(workerGroup, loggingWorker);
            worker.setName(String.format("logWorker-%02d.%02d", this.workers, ii+1));
            worker.setDaemon(true);
            this.threadList.add(worker);
        }
        for (Thread worker : this.threadList) {
            worker.start();
        }
    }

    public boolean add(Object object, int idx) {
        boolean offer = false;
        AbstractTsiPacket packet = (AbstractTsiPacket)object;
        try {
            idx = idx % this.workers;
            offer = this.workerList.get(idx).add(packet);
        }
        catch (Exception e) {
            MDC.put("id", Long.toString(packet.getNodeId()));
            log.error("QUEUE_DATA.add: Exception: {}, {}", packet.getNodeId(), e.getMessage());
            MDC.clear();
        }
        return offer;
    }

    public void stop() {

    }

    public void report() {
        for (AbstractTsiCvimWorker worker : this.workerList) {
            worker.report();
        }
    }
}
