package org.allenai.scienceparse;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;

/**
 * An instance of PaperSource that wraps another, and retries a bunch of times to get the paper
 */
@Slf4j
public class RetryPaperSource extends PaperSource {
    private final PaperSource inner;
    private final int tries;

    public RetryPaperSource(final PaperSource inner) {
        this(inner, 3);
    }

    public RetryPaperSource(final PaperSource inner, final int tries) {
        this.inner = inner;
        this.tries = tries;
    }

    private void wait(int seconds) {
        final long endTime = System.currentTimeMillis() + 1000 * seconds;
        while(System.currentTimeMillis() < endTime) {
            try {
                Thread.sleep(Math.max(endTime - System.currentTimeMillis() + 1, 1));
            } catch(final InterruptedException e) {
                // do nothing
            }
        }
    }

    @Override
    public InputStream getPdf(final String paperId) throws IOException {
        int triesLeft = tries;
        int previousWait = 1;
        int nextWait = 1;

        while(true) {
            triesLeft -= 1;
            try {
                return inner.getPdf(paperId);
            } catch(final IOException e) {
                log.warn(
                        "{} while downloading paper {}, {} tries left",
                        e.getClass().getSimpleName(),
                        paperId,
                        triesLeft);
                if(triesLeft <= 0) {
                    throw e;
                } else {
                    wait(nextWait);
                    final int waited = nextWait;
                    nextWait += previousWait;
                    previousWait = waited;
                }
            }
        }
    }
}
