package com.atlassian.bitbucket.test.rest;

import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.bitbucket.util.PageUtils;
import com.google.common.collect.Maps;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;

public class RestPagedRequest extends AbstractRestRequest {

    private final PageRequest pageRequest;

    protected RestPagedRequest(AbstractPagedRequestBuilder<?, ?> builder) {
        super(builder);

        pageRequest = builder.pageRequest;
    }

    @Nullable
    public PageRequest getPageRequest() {
        return pageRequest;
    }

    @Nonnull
    @Override
    public Map<String, Object> toQueryParams() {
        Map<String, Object> params = Maps.newLinkedHashMap();
        if (pageRequest != null) {
            params.put("start", pageRequest.getStart());
            params.put("limit", pageRequest.getLimit());
        }

        return params;
    }

    public static class Builder extends AbstractPagedRequestBuilder<Builder, RestPagedRequest> {

        public Builder() {
        }

        public Builder(@Nonnull RestPagedRequest request) {
            super(request);
        }

        @Nonnull
        @Override
        public RestPagedRequest build() {
            return new RestPagedRequest(this);
        }

        @Nonnull
        @Override
        protected Builder self() {
            return this;
        }
    }

    protected abstract static class AbstractPagedRequestBuilder<B extends AbstractPagedRequestBuilder<B, R>, R extends RestPagedRequest>
            extends AbstractBuilder<B, R> {

        private PageRequest pageRequest;

        protected AbstractPagedRequestBuilder() {
        }

        protected AbstractPagedRequestBuilder(@Nonnull R request) {
            super(request);

            pageRequest = request.getPageRequest();
        }

        @Nonnull
        public B page(int start, int limit) {
            return page(PageUtils.newRequest(start, limit));
        }

        @Nonnull
        public B page(@Nullable PageRequest value) {
            pageRequest = value;

            return self();
        }
    }
}
