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

import org.xbib.io.webdav.api.DavConstants;
import org.xbib.io.webdav.common.DepthHeader;
import org.xbib.io.webdav.common.IfHeader;
import org.xbib.io.webdav.common.LockInfo;
import org.xbib.io.webdav.common.TimeoutHeader;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Optional;

/**
 * Represents an HTTP LOCK request.
 *
 * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.10">RFC 4918, Section 9.10</a>
 */
public class Lock extends AbstractMethod {

    private final LockInfo lockInfo;

    private final List<String> lockTokens;

    private final long timeout;

    private final boolean isRefresh;

    public Lock(LockInfo lockInfo) {
        this.lockInfo = lockInfo;
        this.timeout = 0L;
        this.lockTokens = null;
        this.isRefresh = false;
    }

    public Lock(long timeout, List<String> lockTokens) {
        this.lockInfo = null;
        this.timeout = timeout;
        this.lockTokens = lockTokens;
        this.isRefresh = true;
    }

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

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

    @Override
    public void accept(HttpRequest.Builder httpRequest) {
        super.accept(httpRequest);
        if (lockInfo != null) {
            TimeoutHeader th = new TimeoutHeader(lockInfo.getTimeout());
            httpRequest.setHeader(th.getHeaderName(), th.getHeaderValue());
            DepthHeader dh = new DepthHeader(lockInfo.isDeep());
            httpRequest.setHeader(dh.getHeaderName(), dh.getHeaderValue());
        }
        if (timeout > 0L) {
            TimeoutHeader th = new TimeoutHeader(timeout);
            httpRequest.setHeader(th.getHeaderName(), th.getHeaderValue());
        }
        if (lockTokens != null) {
            IfHeader ifh = new IfHeader(lockTokens);
            httpRequest.setHeader(ifh.getHeaderName(), ifh.getHeaderValue());
        }
    }

    @Override
    public boolean succeeded(HttpResponse<?> response) {
        boolean lockTokenHeaderOk = isRefresh || getLockToken(response) != null;
        return lockTokenHeaderOk && (response.statusCode() == 200 || response.statusCode() == 201);
    }

    private String getLockToken(HttpResponse<?> response) {
        HttpHeaders httpHeaders = response.headers();
        Optional<String> optional = httpHeaders.firstValue(DavConstants.HEADER_LOCK_TOKEN);
        if (optional.isPresent()) {
            String v = optional.get().trim();
            if (v.startsWith("<") && v.endsWith(">")) {
                return v.substring(1, v.length() - 1);
            }
        }
        return null;
    }
}
