// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.syncbase;

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import io.v.syncbase.core.SyncgroupMemberInfo;
import io.v.syncbase.core.SyncgroupSpec;
import io.v.syncbase.core.VError;
import io.v.syncbase.core.VersionedSyncgroupSpec;
import io.v.syncbase.exception.SyncbaseException;

import static io.v.syncbase.exception.Exceptions.chainThrow;

/**
 * Represents a set of collections, synced amongst a set of users.
 * To get a Syncgroup handle, call {@code Database.syncgroup}.
 */
public class Syncgroup {
    private final Database mDatabase;
    private final io.v.syncbase.core.Syncgroup mCoreSyncgroup;

    Syncgroup(io.v.syncbase.core.Syncgroup coreSyncgroup, Database database) {
        mCoreSyncgroup = coreSyncgroup;
        mDatabase = database;
    }

    void createIfMissing(List<Collection> collections) throws SyncbaseException {
        ArrayList<io.v.syncbase.core.Id> ids = new ArrayList<>();
        for (Collection cx : collections) {
            ids.add(cx.getId().toCoreId());
        }

        SyncgroupSpec spec = new SyncgroupSpec();
        spec.publishSyncbaseName = Syncbase.sOpts.getPublishSyncbaseName();
        spec.permissions = Syncbase.defaultSyncgroupPerms();
        spec.collections = ids;
        spec.mountTables = Syncbase.sOpts.mountPoints;
        spec.isPrivate = false;

        try {
            // TODO(razvanm): Figure out to what value we should set the sync priority in the
            // SyncgroupMemberInfo.
            mCoreSyncgroup.create(spec, new SyncgroupMemberInfo());
        } catch (VError vError) {
            if (vError.id.equals(VError.EXIST)) {
                // Syncgroup already exists.
                // TODO(sadovsky): Verify that the existing syncgroup has the specified
                // configuration, e.g., the specified collections? instead of returning early.
                return;
            }
            chainThrow("creating syncgroup for collections", vError);
        }
    }

    protected void join() throws VError {
        // TODO(razvanm): Find a way to restrict the remote blessing. Cloud is one thing the remote
        // blessings should include.
        mCoreSyncgroup.join("", ImmutableList.of("..."), new SyncgroupMemberInfo());
    }

    /**
     * Returns the id of this syncgroup.
     */
    public Id getId() {
        return new Id(mCoreSyncgroup.getId());
    }

    /**
     * Returns the {@code AccessList} for this syncgroup.
     * Throws if the current user is not an admin of the syncgroup or its collection.
     */
    public AccessList getAccessList() throws SyncbaseException {
        // TODO(alexfandrianto): Rework for advanced users.
        // We will not ask for the syncgroup spec. Instead, we will rely on the collection of this
        // syncgroup to have the correct permissions. There is an issue with not being able to
        // determine READ vs READ_WRITE from just the syncgroup spec because the write tag is only
        // available on the collection. This workaround will assume only a single collection per
        // syncgroup, which is why it might not succeed for advanced users.
        try {

            Id cId = new Id(mCoreSyncgroup.getSpec().syncgroupSpec.collections.get(0));
            return mDatabase.getCollection(cId).getAccessList();

            // return new AccessList(mCoreSyncgroup.getSpec().syncgroupSpec.permissions);

        } catch (VError e) {
            chainThrow("getting access list of syncgroup", getId().getName(), e);
            throw new AssertionError("never happens");
        }
    }

    /**
     * FOR ADVANCED USERS. Configures the behavior of various {@code AccessList} manipulation
     * methods below.
     */
    public static class UpdateAccessListOptions {
        /**
         * If false (the default), the various {@code AccessList} manipulation methods update the
         * {@code AccessList} for the syncgroup and its associated collections. If true, these
         * methods only update the {@code AccessList} for the syncgroup.
         */
        public boolean syncgroupOnly;
    }

    /**
     * FOR ADVANCED USERS. Adds the given users to the syncgroup, with the specified access level.
     */
    public void inviteUsers(List<User> users, AccessList.AccessLevel level,
                            UpdateAccessListOptions opts) throws SyncbaseException {
        AccessList delta = new AccessList();
        for (User u : users) {
            delta.setAccessLevel(u, level);
        }
        updateAccessList(delta, opts);
    }

    /**
     * Adds the given users to the syncgroup, with the specified access level.
     */
    public void inviteUsers(List<User> users, AccessList.AccessLevel level)
            throws SyncbaseException {
        inviteUsers(users, level, new UpdateAccessListOptions());
    }

    /**
     * Adds the given user to the syncgroup, with the specified access level.
     */
    public void inviteUser(User user, AccessList.AccessLevel level) throws SyncbaseException {
        inviteUsers(Collections.singletonList(user), level);
    }

    /**
     * FOR ADVANCED USERS. Removes the given users from the syncgroup.
     */
    public void ejectUsers(List<User> users, UpdateAccessListOptions opts) throws SyncbaseException {
        AccessList delta = new AccessList();
        for (User u : users) {
            delta.removeAccessLevel(u);
        }
        updateAccessList(delta, opts);
    }

    /**
     * Removes the given users from the syncgroup.
     */
    public void ejectUsers(List<User> users) throws SyncbaseException {
        ejectUsers(users, new UpdateAccessListOptions());
    }

    /**
     * Removes the given user from the syncgroup.
     */
    public void ejectUser(User user) throws SyncbaseException {
        ejectUsers(Collections.singletonList(user));
    }

    /**
     * FOR ADVANCED USERS. Applies {@code delta} to the {@code AccessList}.
     */
    public void updateAccessList(final AccessList delta, UpdateAccessListOptions opts)
            throws SyncbaseException {
        try {

            // TODO(sadovsky): Make it so SyncgroupSpec can be updated as part of a batch?
            VersionedSyncgroupSpec versionedSyncgroupSpec = mCoreSyncgroup.getSpec();
            versionedSyncgroupSpec.syncgroupSpec.permissions = AccessList.applyDeltaForSyncgroup(
                    versionedSyncgroupSpec.syncgroupSpec.permissions, delta);
            mCoreSyncgroup.setSpec(versionedSyncgroupSpec);
            // TODO(sadovsky): There's a race here - it's possible for a collection to get destroyed
            // after getSpec() but before db.getCollection().
            final List<io.v.syncbase.core.Id> collectionsIds =
                    versionedSyncgroupSpec.syncgroupSpec.collections;
            mDatabase.runInBatch(new Database.BatchOperation() {
                @Override
                public void run(BatchDatabase db) throws SyncbaseException {
                    for (io.v.syncbase.core.Id id : collectionsIds) {
                        db.getCollection(new Id(id)).updateAccessList(delta);
                    }
                }
            });

        } catch (VError e) {
            chainThrow("updating access list of syncgroup", getId().getName(), e);
        }
    }
}
