package leigh.esp.sutoresu;

import leigh.eo.EO;
import leigh.esp.sdk.ESPClient;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import leigh.mecha.util.UniversalJob;
import leigh.mecha.util.VelocityWatch;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.CountingOutputStream;
import org.apache.commons.io.output.NullOutputStream;

import java.time.Duration;
import java.time.Instant;

public class SutoresuApp {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(SutoresuApp.class);
    private final static String EKO_URI = "/eko/v1";
    private final ESPClient ctx;

    public SutoresuApp(String kabeUrl) {
        ctx = new ESPClient(kabeUrl);
    }

    public static void main(String[] args) {
        if (args.length != 1) {
            logger.info("Usage: SutoresuApp kabe_url");
            System.exit(UniversalJob.RET_BADARGS);
        }

        SutoresuApp app = new SutoresuApp(args[0]);
        app.exercise();
    }

    private void exercise() {
        VelocityWatch vw = new VelocityWatch(logger);
        workerThread(vw, 1000, 1024 * 1024);
    }

    private void workerThread(VelocityWatch vw, int count, int requestData) {
        EO req = new EO();

        req.setValue("replyBytes", requestData);

        String name = Thread.currentThread().getName();

        Instant start = Instant.now();
        logger.info("Attempting {} short link23 transactions...", count);
        for (int i = 0; i < count; i++) {
            try {
                CountingOutputStream cos = new CountingOutputStream(new NullOutputStream());
                ctx.request(EKO_URI, req, is -> IOUtils.copy(is, cos));
                vw.event(name);
                logger.info("Read bytes: {}", cos.getByteCount());
            } catch (Exception e) {
                logger.error("Unable to contact EKO service: {}", e);
                System.exit(UniversalJob.RET_ERROR);
            }
        }
        Instant end = Instant.now();
        Duration length = Duration.between(start, end);

        logger.info("Done. [rate/s: {}] [d: {}}", count / length.getSeconds(), length);
    }
}
