package com.atlassian.bitbucket.mesh.io;

import com.atlassian.bitbucket.mesh.util.BuilderSupport;
import com.google.common.collect.ImmutableSet;

import javax.annotation.Nonnull;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Set;

import static java.util.Objects.requireNonNull;

/**
 * Request to set permissions on a {@link Path}.
 */
public class SetFilePermissionRequest {

    private final Set<FilePermission> groupPermissions;
    private final Set<FilePermission> ownerPermissions;
    private final Path path;
    private final Set<FilePermission> worldPermissions;

    private SetFilePermissionRequest(@Nonnull Builder builder) {
        groupPermissions = builder.groupPermissions.build();
        ownerPermissions = builder.ownerPermissions.build();
        path = builder.path;
        worldPermissions = builder.worldPermissions.build();
    }

    /**
     * Retrieves the {@link FilePermission permissions} granted to members of the owning group.
     *
     * @return the group file permissions to set.
     */
    @Nonnull
    public Set<FilePermission> getGroupPermissions() {
        return groupPermissions;
    }

    /**
     * Retrieves the {@link FilePermission permissions} granted to the file owner.
     *
     * @return the owner file permissions to set.
     */
    @Nonnull
    public Set<FilePermission> getOwnerPermissions() {
        return ownerPermissions;
    }

    /**
     * @return the {@link Path} to set permissions for
     */
    @Nonnull
    public Path getPath() {
        return path;
    }

    @Nonnull
    public Set<FilePermission> getWorldPermissions() {
        return worldPermissions;
    }

    public static class Builder extends BuilderSupport {

        private final ImmutableSet.Builder<FilePermission> groupPermissions;
        private final ImmutableSet.Builder<FilePermission> ownerPermissions;
        private final Path path;
        private final ImmutableSet.Builder<FilePermission> worldPermissions;

        /**
         * @param path the path to set permissions for
         */
        public Builder(@Nonnull Path path) {
            this.path = requireNonNull(path, "path");

            groupPermissions = ImmutableSet.builder();
            ownerPermissions = ImmutableSet.builder();
            worldPermissions = ImmutableSet.builder();
        }

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

        @Nonnull
        public Builder groupPermission(@Nonnull FilePermission permission) {
            addIf(Objects::nonNull, groupPermissions, permission);
            return this;
        }

        @Nonnull
        public Builder groupPermissions(@Nonnull Iterable<FilePermission> permissions) {
            addIf(Objects::nonNull, groupPermissions, permissions);
            return this;
        }

        @Nonnull
        public Builder ownerPermission(@Nonnull FilePermission permission) {
            addIf(Objects::nonNull, ownerPermissions, permission);
            return this;
        }

        @Nonnull
        public Builder ownerPermissions(@Nonnull Iterable<FilePermission> permissions) {
            addIf(Objects::nonNull, ownerPermissions, permissions);
            return this;
        }

        @Nonnull
        public Builder worldPermission(@Nonnull FilePermission permission) {
            addIf(Objects::nonNull, worldPermissions, permission);
            return this;
        }

        @Nonnull
        public Builder worldPermissions(@Nonnull Iterable<FilePermission> permissions) {
            addIf(Objects::nonNull, worldPermissions, permissions);
            return this;
        }
    }
}
