package com.atlassian.bitbucket.mesh.test.util.http;

import com.sun.net.httpserver.HttpExchange;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;

class HttpServletResponseAdapter extends FakeHttpServletResponse {

    private final HttpExchange exchange;
    private final AtomicBoolean responseStarted;

    private int contentLength;

    public HttpServletResponseAdapter(HttpExchange exchange) {
        this.exchange = exchange;

        contentLength = 0;
        responseStarted = new AtomicBoolean(false);
    }

    @Override
    public void addHeader(String name, String value) {
        exchange.getResponseHeaders().add(name, value);
    }

    @Override
    public void flushBuffer() throws IOException {
        ensureResponseStarted();
        exchange.getResponseBody().flush();
    }

    @Override
    public ServletOutputStream getOutputStream() {
        return new ServletOutputStream() {

            volatile OutputStream responseBody = exchange.getResponseBody();

            @Override
            public void close() throws IOException {
                OutputStream responseBody = this.responseBody;
                this.responseBody = null;
                responseBody.close();
            }

            @Override
            public void flush() throws IOException {
                ensureResponseStarted();
                responseBody.flush();
            }

            @Override
            public boolean isReady() {
                return responseBody != null;
            }

            @Override
            public void setWriteListener(WriteListener writeListener) {
                throw new UnsupportedOperationException();
            }

            @Override
            public void write(int b) throws IOException {
                ensureResponseStarted();
                responseBody.write(b);
            }

            @Override
            public void write(byte[] b, int off, int len) throws IOException {
                ensureResponseStarted();
                responseBody.write(b, off, len);
            }
        };
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        ensureResponseStarted();
    }

    @Override
    public void sendError(int sc) throws IOException {
        ensureResponseStarted();
    }

    @Override
    public void sendRedirect(String location) throws IOException {
        setStatus(302);
        exchange.getResponseHeaders().set("Location", location);
        ensureResponseStarted();
    }

    @Override
    public void setContentLength(int len) {
        contentLength = len;
    }

    @Override
    public void setContentType(String type) {
        exchange.getResponseHeaders().set("Content-Type", type);
    }

    @Override
    public void setHeader(String name, String value) {
        exchange.getResponseHeaders().set(name, value);
    }

    private void ensureResponseStarted() throws IOException {
        if (responseStarted.compareAndSet(false, true)) {
            exchange.sendResponseHeaders(getStatus(), contentLength);
        }
    }
}
