// 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 com.google.common.collect.ImmutableMap;

import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import io.v.syncbase.core.Permissions;
import io.v.syncbase.core.Service;
import io.v.syncbase.core.VError;

// FIXME(sadovsky): Currently, various methods throw RuntimeException on any error. We need to
// decide which error types to surface to clients, and define specific Exception subclasses for
// those.

/**
 * The "userdata" collection is a per-user collection (and associated syncgroup) for data that
 * should automatically get synced across a given user's devices. It has the following schema:
 * - /syncgroups/{encodedSyncgroupId} -> null
 * - /ignoredInvites/{encodedSyncgroupId} -> null
 */

/**
 * Syncbase is a storage system for developers that makes it easy to synchronize app data between
 * devices. It works even when devices are not connected to the Internet.
 */
public class Syncbase {
    /**
     * Options for opening a database.
     */
    public static class DatabaseOptions {
        // Where data should be persisted.
        public String rootDir;
        // TODO(sadovsky): Figure out what this should default to.
        public List<String> mountPoints = ImmutableList.of("/ns.dev.v.io:8101/tmp/todos/users/");
        // TODO(sadovsky): Figure out how developers should specify this.
        public String adminUserId = "alexfandrianto@google.com";
        // TODO(sadovsky): Figure out how developers should specify this.
        public String defaultBlessingStringPrefix = "dev.v.io:o:608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com:";
        // FOR ADVANCED USERS. If true, syncgroups will not be published to the cloud peer.
        public boolean disableSyncgroupPublishing;
        // FOR ADVANCED USERS. If true, the user's data will not be synced across their devices.
        public boolean disableUserdataSyncgroup;

        protected String getPublishSyncbaseName() {
            if (disableSyncgroupPublishing) {
                return null;
            }
            return mountPoints.get(0) + "cloud";
        }

        protected String getCloudBlessingString() {
            return "dev.v.io:u:" + adminUserId;
        }
    }

    protected static DatabaseOptions sOpts;
    private static Database sDatabase;
    private static Map sSelfAndCloud;

    // TODO(sadovsky): Maybe set DB_NAME to "db__" so that it is less likely to collide with
    // developer-specified names.

    protected static final String
            TAG = "syncbase",
            DIR_NAME = "syncbase",
            DB_NAME = "db",
            USERDATA_SYNCGROUP_NAME = "userdata__";

    protected static void enqueue(final Runnable r) {
        // Note, we use Timer rather than Handler because the latter must be mocked out for tests,
        // which is rather annoying.
        //new Handler().post(r);
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                r.run();
            }
        }, 0);
    }

    public static abstract class DatabaseCallback {
        public void onSuccess(Database db) {
        }

        public void onError(Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Starts Syncbase if needed; creates default database if needed; performs create-or-join for
     * "userdata" syncgroup if needed. The passed callback is called on the current thread.
     * Fails if the user is not logged in.
     *
     * @param opts options for database creation
     * @param cb   the callback to call with the database handle
     */
    public static void database(final DatabaseCallback cb, DatabaseOptions opts) {
        // TODO(sadovsky): The create-or-join forces this method to be async, which is annoying
        // since create-or-join will no longer be necessary once syncgroup merge is supported.
        if (sDatabase != null) {
            // TODO(sadovsky): Check that opts matches original opts (sOpts)?
            Syncbase.enqueue(new Runnable() {
                @Override
                public void run() {
                    cb.onSuccess(sDatabase);
                }
            });
            return;
        }
        sOpts = opts;
        sSelfAndCloud = ImmutableMap.of(
                Permissions.IN, ImmutableList.of(getPersonalBlessingString(),
                        sOpts.getCloudBlessingString()));
        // TODO(razvanm): Surface Cgo function to shut down syncbase.
        try {
            // TODO(razvanm): Use just the name after Blessings.AppBlessingFromContext starts
            // working.
            sDatabase = new Database(Service.database(new io.v.syncbase.core.Id("...", DB_NAME)));
            sDatabase.createIfMissing();
        } catch (final VError vError) {
            enqueue(new Runnable() {
                @Override
                public void run() {
                    cb.onError(vError);
                }
            });
            return;
        }

        if (sOpts.disableUserdataSyncgroup) {
            Database.CollectionOptions cxOpts = new DatabaseHandle.CollectionOptions();
            cxOpts.withoutSyncgroup = true;
            try {
                sDatabase.collection(USERDATA_SYNCGROUP_NAME, cxOpts);
            } catch (VError vError) {
                cb.onError(vError);
                return;
            }
            Syncbase.enqueue(new Runnable() {
                @Override
                public void run() {
                    cb.onSuccess(sDatabase);
                }
            });
        } else {
            // FIXME(sadovsky): Implement create-or-join (and watch) of userdata syncgroup. For the
            // new JNI API, we'll need to add Go code for this, since Java can't make RPCs.
            cb.onError(new RuntimeException("Synced userdata collection is not yet supported"));
        }
    }

    /**
     * Returns true iff the user is currently logged in.
     */
    public static boolean isLoggedIn() {
        throw new RuntimeException("Not implemented");
    }

    /**
     * Returns the currently logged in user.
     */
    public static User getLoggedInUser() {
        throw new RuntimeException("Not implemented");
    }

    /**
     * Logs in the user associated with the given OAuth token and provider.
     * <p/>
     * A mapping of providers and OAuth token scopes are listed below:
     * google: https://www.googleapis.com/auth/userinfo.email
     * <p/>
     * Note: Unlisted providers are unsupported.
     *
     * @param authToken The OAuth token for the user to be logged in.
     * @param provider  The provider of the OAuth token.
     */
    public static void login(String authToken, String provider) {
        if (!provider.equals("google")) {
            throw new RuntimeException("Unsupported provider: " + provider);
        }
        throw new RuntimeException("Not implemented");
    }

    /**
     * Scans the neighborhood for nearby users.
     *
     * @param cb The callback to call when a User is found or lost.
     */
    public static void scanNeighborhoodForUsers(ScanNeighborhoodForUsersCallback cb) {
        throw new RuntimeException("Not implemented");
    }

    public static abstract class ScanNeighborhoodForUsersCallback {
        public abstract void onFound(User user);

        public abstract void onLost(User user);

        public void onError(Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Advertises the logged in user's presence to those around them.
     */
    public static void advertiseLoggedInUserInNeighborhood() {
        throw new RuntimeException("Not implemented");
    }

    /**
     * Advertises the logged in user's presence to a limited set of users who must be around them.
     *
     * @param usersWhoCanSee The set of users who are allowed to find this user.
     */
    public static void advertiseLoggedInUserInNeighborhood(Iterable<User> usersWhoCanSee) {
        throw new RuntimeException("Not implemented");
    }

    /**
     * Stops advertising the presence of the logged in user so that they can no longer be found.
     */
    public static void stopAdvertisingLoggedInUserInNeighborhood() {
        throw new RuntimeException("Not implemented");
    }

    /**
     * Returns true iff this person appears in the neighborhood.
     */
    public static boolean isAdvertisingLoggedInUserInNeighborhood() {
        throw new RuntimeException("Not implemented");
    }

    protected static String getBlessingStringFromEmail(String email) {
        return sOpts.defaultBlessingStringPrefix + email;
    }

    protected static String getEmailFromBlessingPattern(String blessingStr) {
        String[] parts = blessingStr.split(":");
        return parts[parts.length - 1];
    }

    protected static String getPersonalBlessingString() {
        // TODO(razvanm): Switch to Blessings.UserBlessingFromContext() after the lower level
        // starts working.
        return "...";
    }

    protected static Permissions defaultDatabasePerms() throws VError {
        // TODO(sadovsky): Revisit these default perms, which were copied from the Todos app.
        Map anyone = ImmutableMap.of(Permissions.IN, ImmutableList.of("..."));
        return new Permissions(ImmutableMap.of(
                Permissions.Tags.RESOLVE, anyone,
                Permissions.Tags.READ, sSelfAndCloud,
                Permissions.Tags.WRITE, sSelfAndCloud,
                Permissions.Tags.ADMIN, sSelfAndCloud));
    }

    protected static Permissions defaultCollectionPerms() throws VError {
        // TODO(sadovsky): Revisit these default perms, which were copied from the Todos app.
        return new Permissions(ImmutableMap.of(
                Permissions.Tags.READ, sSelfAndCloud,
                Permissions.Tags.WRITE, sSelfAndCloud,
                Permissions.Tags.ADMIN, sSelfAndCloud));
    }

    protected static Permissions defaultSyncgroupPerms() throws VError {
        // TODO(sadovsky): Revisit these default perms, which were copied from the Todos app.
        return new Permissions(ImmutableMap.of(
                Permissions.Tags.READ, sSelfAndCloud,
                Permissions.Tags.ADMIN, sSelfAndCloud));
    }
}