// 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.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);
        } 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.
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(androidCtx);
            String userEmail = prefs.getString(SignInActivity.PREF_USER_ACCOUNT_NAME, "");
            activity.startActivityForResult(
                    BlessingService.newBlessingIntent(androidCtx, userEmail),
                    BLESSING_REQUEST);
            return;
        }
        asyncConfigurePrincipal(blessings);
    }

    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;
    }

    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()));
    }

    private void asyncConfigurePrincipal(final Blessings blessings) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                configurePrincipal(blessings);
            }
        });
    }

    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;
        }
    }

}
