// 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.mCloudName;
        spec.permissions = Syncbase.defaultSyncgroupPerms();
        spec.collections = ids;
        spec.mountTables = Syncbase.sOpts.mMountPoints;
        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.
        mCoreSyncgroup.join(Syncbase.sOpts.mCloudName, 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);
        }
    }
}
