package com.atlassian.stash.internal.repository.ref.restriction.rest;

import com.atlassian.bitbucket.repository.ref.restriction.*;
import com.atlassian.bitbucket.rest.RestMapEntity;
import com.atlassian.bitbucket.rest.user.RestApplicationUser;
import com.atlassian.bitbucket.rest.util.RestPage;
import com.atlassian.bitbucket.util.PageImpl;
import com.atlassian.bitbucket.util.PageRequestImpl;
import com.atlassian.stash.internal.repository.ref.restriction.SimpleGroupAccessGrant;
import com.atlassian.stash.internal.repository.ref.restriction.SimpleRefRestriction;
import com.atlassian.stash.internal.repository.ref.restriction.SimpleUserAccessGrant;
import com.atlassian.stash.internal.repository.ref.restriction.provider.PatternMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import java.util.Collection;
import java.util.List;

import static java.util.stream.Collectors.toList;

public class RestRefRestriction extends RestMapEntity {

    private final String ID = "id";
    protected final String TYPE = "type";
    protected final String MATCHER = "matcher";
    protected static final String USERS = "users";
    protected static final String GROUPS = "groups";

    public RestRefRestriction() {
    }

    public RestRefRestriction(RefRestriction restriction) {
        this(restriction.getId(), restriction.getType().getId(), new RestRefMatcher(restriction.getMatcher()), restriction.getAccessGrants());
    }

    protected RestRefRestriction(int id, String type, RestRefMatcher matcher, List<AccessGrant> accessGrants) {
        put(ID, id);
        put(TYPE, type);
        put(MATCHER, matcher);
        put(USERS, accessGrants
                .stream()
                .filter(grant -> grant instanceof UserAccessGrant)
                .map(UserAccessGrant.class::cast)
                .map(UserAccessGrant::getUser)
                .map(RestApplicationUser::new)
                .collect(toList()));
        put(GROUPS, accessGrants.stream()
                .filter(grant -> grant instanceof GroupAccessGrant)
                .map(GroupAccessGrant.class::cast)
                .map(GroupAccessGrant::getGroup)
                .collect(toList()));
    }

    public int getId() {
        return getIntProperty(ID);
    }

    public RestRefMatcher getMatcher() {
        return RestRefMatcher.valueOf(get(MATCHER));
    }

    public String getType() {
        return getStringProperty(TYPE);
    }

    public Collection<RestApplicationUser> getUsers() {
        return (Collection<RestApplicationUser>) get(USERS);
    }

    public Collection<String> getGroups() {
        return (Collection<String>) get(GROUPS);
    }

    private static final List<AccessGrant> EXAMPLE_ACCESS_GRANTS = ImmutableList.of(
            new SimpleUserAccessGrant(RestApplicationUser.RESPONSE_EXAMPLE),
            new SimpleGroupAccessGrant("bitbucket-users")
    );

    public static final RestRefRestriction RESPONSE_EXAMPLE = new RestRefRestriction(new SimpleRefRestriction(2, 2, new PatternMatcher("release*", false), RefRestrictionType.READ_ONLY, EXAMPLE_ACCESS_GRANTS));
    public static final RestPage<RestRefRestriction> SEARCH_EXAMPLE = new RestPage<>(new PageImpl<>(new PageRequestImpl(1, 25),
            Lists.newArrayList(
                    RESPONSE_EXAMPLE,
                    new RestRefRestriction(new SimpleRefRestriction(2, 2, new PatternMatcher("feature/**", false), RefRestrictionType.PULL_REQUEST_ONLY, ImmutableList.of()))),
            true));

    public static final List<RestRefRestriction> BULK_RESPONSE_EXAMPLE = ImmutableList.of(RESPONSE_EXAMPLE);
}
