// 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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import io.v.syncbase.core.Permissions;
import io.v.syncbase.core.SyncgroupMemberInfo;
import io.v.syncbase.core.SyncgroupSpec;
import io.v.syncbase.core.VError;
import io.v.syncbase.core.VersionedSyncgroupSpec;

/**
 * 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;

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

    protected void createIfMissing(List<Collection> collections) throws VError {
        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;
            }
            throw vError;
        }
    }

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

    /**
     * Returns the {@code AccessList} for this syncgroup.
     */
    public AccessList getAccessList() throws VError {
        return new AccessList(mCoreSyncgroup.getSpec().syncgroupSpec.permissions);
    }

    /**
     * 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 VError {
        AccessList delta = new AccessList();
        for (User u : users) {
            delta.users.put(u.getAlias(), 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 VError {
        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 VError {
        inviteUsers(Collections.singletonList(user), level);
    }

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

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

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

    /**
     * FOR ADVANCED USERS. Applies {@code delta} to the {@code AccessList}.
     */
    public void updateAccessList(final AccessList delta, UpdateAccessListOptions opts)
            throws VError {
        // TODO(sadovsky): Make it so SyncgroupSpec can be updated as part of a batch?
        VersionedSyncgroupSpec versionedSyncgroupSpec;
        try {
            versionedSyncgroupSpec = mCoreSyncgroup.getSpec();
        } catch (VError vError) {
            throw new RuntimeException("getSpec failed", vError);
        }
        Permissions newPermissions = AccessList.applyDelta(
                versionedSyncgroupSpec.syncgroupSpec.permissions, delta);
        versionedSyncgroupSpec.syncgroupSpec.permissions = newPermissions;
        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) {
                for (io.v.syncbase.core.Id id : collectionsIds) {
                    try {
                        db.getCollection(new Id(id)).updateAccessList(delta);
                    } catch (VError vError) {
                        throw new RuntimeException("getCollection failed", vError);
                    }
                }
            }
        }, new Database.BatchOptions());
    }
}
