package com.ruoyi.generator.service.front;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.concurrent.TimeUnit;

final class ManagedPreviewProcess extends Process
{
    private final Process delegate;
    private final File pidFile;

    ManagedPreviewProcess(Process delegate, File pidFile)
    {
        this.delegate = delegate;
        this.pidFile = pidFile;
    }

    long waitForRootPid(long timeoutMillis)
    {
        long deadline = System.currentTimeMillis() + timeoutMillis;
        do
        {
            Long pid = readRootPid();
            if (pid != null)
            {
                return pid.longValue();
            }
            sleepQuietly(25L);
        }
        while (System.currentTimeMillis() < deadline && delegate.isAlive());
        return -1L;
    }

    void deletePidFile()
    {
        if (pidFile.isFile())
        {
            pidFile.delete();
        }
    }

    private Long readRootPid()
    {
        if (!pidFile.isFile())
        {
            return null;
        }
        try
        {
            String value = new String(Files.readAllBytes(pidFile.toPath()), StandardCharsets.UTF_8).trim();
            long pid = Long.parseLong(value);
            return pid > 0L ? Long.valueOf(pid) : null;
        }
        catch (IOException ignored)
        {
            return null;
        }
        catch (NumberFormatException ignored)
        {
            return null;
        }
    }

    private void sleepQuietly(long millis)
    {
        try
        {
            Thread.sleep(millis);
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
    }

    @Override
    public OutputStream getOutputStream()
    {
        return delegate.getOutputStream();
    }

    @Override
    public InputStream getInputStream()
    {
        return delegate.getInputStream();
    }

    @Override
    public InputStream getErrorStream()
    {
        return delegate.getErrorStream();
    }

    @Override
    public int waitFor() throws InterruptedException
    {
        return delegate.waitFor();
    }

    @Override
    public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException
    {
        return delegate.waitFor(timeout, unit);
    }

    @Override
    public int exitValue()
    {
        return delegate.exitValue();
    }

    @Override
    public void destroy()
    {
        delegate.destroy();
    }

    @Override
    public Process destroyForcibly()
    {
        delegate.destroyForcibly();
        return this;
    }

    @Override
    public boolean isAlive()
    {
        return delegate.isAlive();
    }
}
