package org.xbib.io.webdav.client.methods;

import org.xbib.io.webdav.api.DavConstants;
import org.xbib.io.webdav.common.CodedUrlHeader;
import org.xbib.io.webdav.common.DepthHeader;
import org.xbib.io.webdav.common.SubscriptionInfo;
import org.xbib.io.webdav.common.TimeoutHeader;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Optional;

/**
 * Represents an HTTP SUBSCRIBE request.
 * Note that "SUBSCRIBE" is a custom HTTP extension, not defined in a standards paper.
 */
public class Subscribe extends AbstractMethod {

    private final SubscriptionInfo subscriptionInfo;

    private final String subscriptionId;

    public Subscribe(SubscriptionInfo subscriptionInfo, String subscriptionId) {
        this.subscriptionInfo = subscriptionInfo;
        this.subscriptionId = subscriptionId;
    }

    @Override
    public void accept(HttpRequest.Builder httpRequest) {
        super.accept(httpRequest);
        if (subscriptionId != null) {
            CodedUrlHeader h = new CodedUrlHeader("SubscriptionId", subscriptionId);
            httpRequest.setHeader(h.getHeaderName(), h.getHeaderValue());
        }
        // optional timeout header
        long to = subscriptionInfo.getTimeOut();
        if (to != DavConstants.UNDEFINED_TIMEOUT) {
            TimeoutHeader h = new TimeoutHeader(subscriptionInfo.getTimeOut());
            httpRequest.setHeader(h.getHeaderName(), h.getHeaderValue());
        }
        // always set depth header since value is boolean flag
        DepthHeader dh = new DepthHeader(subscriptionInfo.isDeep());
        httpRequest.setHeader(dh.getHeaderName(), dh.getHeaderValue());
    }

    public String getSubscriptionId(HttpResponse<byte[]> response) {
        Optional<String> optional = response.headers().firstValue("SubscriptionId");
        return optional.map(s -> new CodedUrlHeader("SubscriptionId", s).getCodedUrl()).orElse(null);
    }

    @Override
    public String method() {
        return "SUBSCRIBE";
    }

    @Override
    public HttpRequest.BodyPublisher bodyPublisher() {
        return publish(subscriptionInfo);
    }

    @Override
    public boolean succeeded(HttpResponse<?> response) {
        return response.statusCode() == 200;
    }
}