// Copyright 2015 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.android.apps.syncslides.misc;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import org.joda.time.Duration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.v.android.apps.syncslides.SignInActivity;
import io.v.android.apps.syncslides.db.DB;
import io.v.android.libs.security.BlessingsManager;
import io.v.android.v23.V;
import io.v.android.v23.services.blessing.BlessingCreationException;
import io.v.android.v23.services.blessing.BlessingService;
import io.v.impl.google.naming.NamingUtil;
import io.v.v23.context.VContext;
import io.v.v23.namespace.Namespace;
import io.v.v23.naming.Endpoint;
import io.v.v23.naming.GlobReply;
import io.v.v23.naming.MountEntry;
import io.v.v23.naming.MountedServer;
import io.v.v23.rpc.ListenSpec;
import io.v.v23.rpc.Server;
import io.v.v23.rpc.ServerState;
import io.v.v23.security.BlessingPattern;
import io.v.v23.security.Blessings;
import io.v.v23.security.VPrincipal;
import io.v.v23.security.VSecurity;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

/**
 * Does vanadium stuff - MT scanning, service creation, unmounting, etc.
 *
 * This class is a singleton, since all vanadium activity must involve a
 * Vanadium context recovered from a static call to V.init, ultimately (ideally)
 * bookended by a static call to V.shutdown.   In an app.Service, one could call
 * these in onCreate and onDestroy respectively.
 */
public class V23Manager {
    public static final Duration MT_TIMEOUT =
            Duration.standardSeconds(10);
    public static final int BLESSING_REQUEST = 201;
    private static final String TAG = "V23Manager";
    private static final ExecutorService mExecutor =
            Executors.newSingleThreadExecutor();
    private Context mAndroidCtx;
    private VContext mBaseContext = null;
    private Blessings mBlessings = null;
    // Can only have one of these at the moment.  Could add more...
    private Server mLiveServer = null;

    // Singleton.
    private V23Manager() {
    }

    private static Blessings loadBlessings(Context context) {
        Log.d(TAG, "loadBlessings from prefs");
        try {
            // See if there are blessings stored in shared preferences.
            return BlessingsManager.getBlessings(context);
        } catch (VException e) {
            Log.w(TAG, "Cannot get blessings from prefs: " + e.getMessage());
        }
        return null;
    }

    /**
     * To be called from an Activity's onActivityResult method, e.g.
     *     public void onActivityResult(
     *         int requestCode, int resultCode, Intent data) {
     *         if (V23Manager.onActivityResult(
     *             getApplicationContext(), requestCode, resultCode, data)) {
     *           return;
     *         }
     *     }
     */
    public static boolean onActivityResult(
            Context androidCtx, int requestCode, int resultCode, Intent data) {
        Log.d(TAG, "onActivityResult");
        if (requestCode != BLESSING_REQUEST) {
            return false;
        }
        try {
            Log.d(TAG, "unpacking blessing");
            Blessings blessings = unpackBlessings(androidCtx, resultCode, data);
            Singleton.get().configurePrincipal(blessings);
            DB.Singleton.get(androidCtx).init();
        } catch (BlessingCreationException e) {
            throw new IllegalStateException(e);
        } catch (VException e) {
            throw new IllegalStateException(e);
        }
        return true;
    }

    public static Blessings unpackBlessings(
            Context androidCtx, int resultCode, Intent data)
            throws BlessingCreationException, VException {
        byte[] blessingsVom = BlessingService.extractBlessingReply(
                resultCode, data);
        Blessings blessings = (Blessings) VomUtil.decode(
                blessingsVom, Blessings.class);
        BlessingsManager.addBlessings(androidCtx, blessings);
        Toast.makeText(androidCtx, "Got blessings", Toast.LENGTH_SHORT).show();
        return blessings;
    }

    /**
     * @return IP address of the mounttable to scan.
     */
    public static List<String> determineNamespaceRoot() {
        List<String> result = new ArrayList<>();
        result.add("/" + Config.MT_ADDRESS);
        return result;
    }

    public static String syncName(String id) {
        return NamingUtil.join("/", Config.MT_ADDRESS, id);
    }

    public VContext getVContext() {
        return mBaseContext;
    }

    public void init(Context androidCtx, Activity activity) {
        init(androidCtx, null, activity);
    }

    public synchronized void init(
            Context androidCtx, Blessings otherBlessings, Activity activity) {
        Log.d(TAG, "init");
        if (mAndroidCtx != null) {
            if (mAndroidCtx == androidCtx) {
                Log.d(TAG, "Initialization already started.");
                return;
            } else {
                Log.d(TAG, "Initialization with new context.");
                shutdown(Behavior.STRICT);
            }
        }
        Blessings blessings = otherBlessings;
        mAndroidCtx = androidCtx;
        // Must call V.init before attempting to load blessings, so that proper
        // code is loaded.
        mBaseContext = V.init(mAndroidCtx);
        if (blessings == null) {
            blessings = loadBlessings(androidCtx);
        }
        Namespace ns = V.getNamespace(mBaseContext);
        try {
            ns.setRoots(determineNamespaceRoot());
            Log.d(TAG, "Set namespace root to: " + determineNamespaceRoot());
        } catch (VException e) {
            throw new IllegalStateException("Unable to set namespace.");
        }
        if (blessings == null) {
            Log.d(TAG, "No blessings - firing activity " + activity.getTitle());
            // Bail out and go get them, and re-enter init with them.
            if (activity == null) {
                throw new IllegalArgumentException(
                        "Cannot get blessings without an activity to return to.");
            }
            // Get the signed-in user's email to generate the blessings from.
            String userEmail = SignInActivity.getUserEmail(androidCtx);
            activity.startActivityForResult(
                    BlessingService.newBlessingIntent(androidCtx, userEmail),
                    BLESSING_REQUEST);
            return;
        }
        configurePrincipal(blessings);
        DB.Singleton.get(mAndroidCtx).init();
    }

    public void flushServerFromCache(String name) {
        V.getNamespace(mBaseContext).flushCacheEntry(mBaseContext, name);
    }

    /**
     * v23 operations that require a blessing (almost everything) will fail if
     * attempted before this is true.
     *
     * The simplest usage is 1) There are no blessings. 2) An activity starts
     * and calls V23Manager.init. 2) init notices there are no blessings and
     * calls startActivityForResult 3) meanwhile, the activity and/or its
     * components still run, but can test isBlessed before attempting anything
     * requiring blessings. The activity will soon be re-initialized anyway. 4)
     * user kicked over into 'account manager', gets a blessing, and the
     * activity is restarted, this time with isBlessed == true.
     */
    public boolean isBlessed() {
        return mBlessings != null;
    }

    /**
     * Returns the blessings for this process.
     */
    public Blessings getBlessings() {
        return mBlessings;
    }

    private void configurePrincipal(final Blessings blessings) {
        Log.d(TAG, "configurePrincipal: blessings=" +
                (blessings == null ? "null" : blessings.toString()));
        try {
            VPrincipal p = V.getPrincipal(mBaseContext);
            p.blessingStore().setDefaultBlessings(blessings);
            p.blessingStore().set(blessings, new BlessingPattern("..."));
            VSecurity.addToRoots(p, blessings);
            mBlessings = blessings;
        } catch (VException e) {
            Log.e(TAG, String.format(
                    "Couldn't set local blessing %s: %s",
                    blessings, e.getMessage()));
        }
        Log.d(TAG, "blessings stored: " +
                (mBlessings == null ? "NONE!" : mBlessings.toString()));
    }

    public void shutdown(Behavior behavior) {
        Log.d(TAG, "Shutdown");
        if (mAndroidCtx == null) {
            if (behavior == Behavior.STRICT) {
                throw new IllegalStateException(
                        "Shutdown called on uninitialized manager.");
            }
            Log.d(TAG, "Was never initialized.");
            return;
        }
        V.shutdown();
        mAndroidCtx = null;
    }

    private void error(String msg) {
        Log.e(TAG, msg);
        Toast.makeText(mAndroidCtx, msg, Toast.LENGTH_LONG).show();
    }

    public Set<String> scan(String pattern) {
        FirstGrabber grabber = new FirstGrabber();
        scan(pattern, grabber);
        return grabber.result;
    }

    /**
     * For every server, take the first endpoint, ignore the rest.
     */
    private class FirstGrabber implements Visitor {
        final HashSet<String> result = new HashSet<>();

        public void visit(MountEntry entry) {
            Log.d(TAG, "  Entry: \"" + entry.getName() + "\"");
            result.add(entry.getName());
            final boolean logEndpoints = true;
            if (logEndpoints) {
                for (MountedServer server : entry.getServers()) {
                    Log.d(TAG, "  endPoint: \"" + server.getServer() + "\"");
                }
            }
        }
    }

    public void scan(String pattern, Visitor visitor) {
        try {
            VContext ctx = mBaseContext.withTimeout(MT_TIMEOUT);
            Namespace ns = V.getNamespace(ctx);
            for (GlobReply reply : ns.glob(ctx, pattern)) {
                if (reply instanceof GlobReply.Entry) {
                    visitor.visit(((GlobReply.Entry) reply).getElem());
                }
            }
        } catch (VException e) {
            // TODO(jregan): Handle total v23 failure higher up the stack.
            throw new IllegalStateException(e);
        }
    }

    private VContext getListenContext() throws VException {
        final boolean useProxy = false;
        // Disabled while debugging network performance / visibility issues.
        if (useProxy) {
            ListenSpec spec = V.getListenSpec(mBaseContext).withProxy("proxy");
            //ListenSpec spec = V.getListenSpec(mBaseContext).withAddress(
            //        new ListenSpec.Address("tcp", "0.0.0.0:0"));
            Log.d(TAG, "spec : " + spec.toString());
            Log.d(TAG, "spec proxy: " + spec.getProxy().toString());
            return V.withListenSpec(mBaseContext, spec);
        }
        return mBaseContext;
    }

    private Server makeServer(String mountName, Object server) throws VException {
        return V.getServer(
                V.withNewServer(
                        getListenContext(),
                        mountName,
                        server,
                        VSecurity.newAllowEveryoneAuthorizer()));
    }

    public void mount(final String mountName, final Object server) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "mounting on name \"" + mountName +
                        "\" at table " + Config.MT_ADDRESS);
                try {
                    mLiveServer = makeServer(mountName, server);
                    Log.d(TAG, "  Server status proxies: " +
                            Arrays.deepToString(
                                    mLiveServer.getStatus().getProxies()));
                    Endpoint[] points = mLiveServer.getStatus().getEndpoints();
                    for (Endpoint point : points) {
                        Log.d(TAG, "  Listening on: " + point);
                    }
                    if (points.length < 1) {
                        throw new IllegalStateException("No endpoints!");
                    }
                } catch (VException e) {
                    // TODO(jregan): java gymnastics to propagate exceptions
                    // to a callback instead of throwing over a cliff.
                    throw new IllegalStateException(e);
                }
                Log.d(TAG, "Done mounting on name \"" + mountName + "\"");
            }
        });
    }

    public void unMount() {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "unMount");
                if (mLiveServer == null) {
                    return;
                }
                if (mLiveServer.getStatus().getState() != ServerState.SERVER_ACTIVE) {
                    throw new IllegalStateException("v32 service not active.");
                }
                try {
                    mLiveServer.stop();
                } catch (VException e) {
                    throw new IllegalStateException(e);
                }
                Log.d(TAG, "unMounted server.");
                mLiveServer = null;
            }
        });
    }

    public enum Behavior {PERMISSIVE, STRICT}

    public interface Visitor {
        void visit(MountEntry entry);
    }

    public static class Singleton {
        private static volatile V23Manager instance;

        public static V23Manager get() {
            V23Manager result = instance;
            if (instance == null) {
                synchronized (Singleton.class) {
                    result = instance;
                    if (result == null) {
                        instance = result = new V23Manager();
                    }
                }
            }
            return result;
        }
    }

}
