// 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.libs.security;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import java.security.interfaces.ECPublicKey;
import java.util.UUID;

import io.v.android.impl.google.services.blessing.BlessingActivity;
import io.v.android.v23.V;
import io.v.v23.VFutures;
import io.v.v23.context.VContext;
import io.v.v23.security.Blessings;
import io.v.v23.security.Constants;
import io.v.v23.security.VPrincipal;
import io.v.v23.security.VSecurity;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

/**
 * Manages {@link Blessings} for a given Android application, persisting them in its
 * shared preferences.
 * <p>
 * This class is thread-safe.
 */
public class BlessingsManager extends Fragment {
    private static String TAG = "BlessingsManager";

    private static final int REQUEST_CODE_MINT_BLESSINGS = 1000;
    private static final String STATE_SAVED = "STATE_SAVED";

    private static SettableFuture<Blessings> mintFuture;

    private VContext mBaseContext;
    private boolean mWasDestroyed = false;
    private String mPrefKey;                   // may be null if wasDestroyed == true
    private String mGoogleAccount;             // may be null if wasDestroyed == true

    /**
     * Returns a new {@link ListenableFuture} whose result are the {@link Blessings} found in
     * {@link SharedPreferences} under the given key.
     * <p>
     * If no {@link Blessings} are found, mints a new set of {@link Blessings} and stores them
     * in {@link SharedPreferences} under the provided key.
     * <p>
     * This method may start an activity to handle the creation of new blessings, if needed.
     * Hence, you should be prepared that your activity may be stopped and re-started.
     * <p>
     * This method is re-entrant: if blessings need to be minted, multiple concurrent invocations
     * of this method will result in only the last invocation's future ever being invoked.  This
     * means that it's safe to call this method from any of the android's lifecycle methods
     * (e.g., onCreate(), onStart(), onResume()).
     * <p>
     * This method must be invoked on the UI thread.
     *
     * @param context      Vanadium context
     * @param activity     android {@link Activity} requesting blessings
     * @param key          a key under which the blessings are stored
     * @param setAsDefault if true, the returned {@link Blessings} will be set as default
     *                     blessings for the app
     * @return             a new {@link ListenableFuture} whose result are the blessings
     *                     persisted under the given key
     */
    public static ListenableFuture<Blessings> getBlessings(VContext context,
            final Activity activity, String key, boolean setAsDefault) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            return Futures.immediateFailedFuture(new VException("getBlessings() must be invoked " +
                    "on the UI thread"));
        }
        try {
            Blessings blessings = readBlessings(context, activity, key, setAsDefault);
            if (blessings != null) {
                return Futures.immediateFuture(blessings);
            }
        } catch (VException e) {
            Log.e(TAG, "Malformed blessings in SharedPreferences. Minting new blessings: " +
                    e.getMessage());
        }
        return mintBlessings(context, activity, key, setAsDefault);
    }

    /**
     * Returns {@link Blessings} found in {@link SharedPreferences} under the given key.
     * <p>
     * Unlike {@link #getBlessings}, if no {@link Blessings} are found this method won't mint a new
     * set of {@link Blessings}; instead, {@code null} value is returned.
     *
     * @param context         Vanadium context
     * @param androidContext  android {@link Context} requesting blessings
     * @param key             a key under which the blessings are stored
     * @param setAsDefault    if true, the returned {@link Blessings}, if non-{@code null}, will be
     *                        set as default blessings for the app
     * @return                {@link Blessings} found in {@link SharedPreferences} under the given
     *                        key or {@code null} if no blessings are found
     * @throws VException     if the blessings are found in {@link SharedPreferences} but they
     *                        are invalid
     */
    public static Blessings readBlessings(VContext context, Context androidContext, String key,
                                          boolean setAsDefault) throws VException {
        String blessingsVom =
                PreferenceManager.getDefaultSharedPreferences(androidContext).getString(key, "");
        if (blessingsVom == null || blessingsVom.isEmpty()) {
            return null;
        }
        Blessings blessings = (Blessings) VomUtil.decodeFromString(blessingsVom, Blessings.class);
        if (blessings == null) {
            throw new VException("Couldn't decode blessings: got null blessings");
        }
        // TODO(spetrovic): validate the blessings and fail if they aren't valid
        return setAsDefault ?
                VFutures.sync(wrapWithSetAsDefault(
                    context, androidContext, Futures.immediateFuture(blessings)))
                : blessings;
    }

    /**
     * Mints a new set of {@link Blessings} that are persisted in {@link SharedPreferences} under
     * the provided key.
     * <p>
     * If {@code googleAccount} is non-{@code null} and non-empty, mints the blessings using
     * that account;  otherwise, prompts the user to pick one of the installed Google accounts
     * (if there is more than one installed).
     * <p>
     * This method will start an activity to handle the creation of new blessings.  Hence, you
     * should be prepared that your activity will be stopped and re-started, at the minimum.
     * <p>
     * This method is re-entrant: if invoked the 2nd time while the 1st invocation is still
     * pending, the future associated with the 2nd invocation will overwrite the 1st future: the
     * 1st future will never be invoked.
     * <p>
     * This method must be invoked on the UI thread.
     *
     * @param activity      android {@link Activity} requesting blessings
     * @param key           a key in {@link SharedPreferences} under which the newly minted
     *                      blessings are persisted
     * @param googleAccount a Google account to use to mint the blessings; if {@code null} or
     *                      empty, user will be prompted to pick one of the installed Google
     *                      accounts, if there is more than one installed
     * @param setAsDefault  if true, the returned {@link Blessings} will be set as default
     *                      blessings for the app
     * @return              a new {@link ListenableFuture} whose result are the newly minted
     *                      {@link Blessings}
     */
    public static ListenableFuture<Blessings> mintBlessings(VContext ctx,
            final Activity activity, String key, String googleAccount, boolean setAsDefault) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            return Futures.immediateFailedFuture(new VException("mintBlessings() must be invoked " +
                    "on the UI thread"));
        }
        if (mintFuture != null) {
            // Mint already in progress, which means that the invoking activity has been
            // destroyed and then recreated.  Register the new future to be invoked on completion
            // of that mint.  Note that it is safe and desirable to override the old future
            // as it's invocation would be handled by a destroyed activity.
            mintFuture = SettableFuture.create();
            return setAsDefault ? wrapWithSetAsDefault(ctx, activity, mintFuture) : mintFuture;
        }
        mintFuture = SettableFuture.create();
        FragmentTransaction transaction = activity.getFragmentManager().beginTransaction();
        BlessingsManager fragment = new BlessingsManager();
        fragment.mPrefKey = key;
        fragment.mGoogleAccount = googleAccount;
        transaction.add(fragment, UUID.randomUUID().toString());
        transaction.commit();  // this will invoke the fragment's onCreate() immediately.
        return setAsDefault ? wrapWithSetAsDefault(ctx, activity, mintFuture) : mintFuture;
    }

    /**
     * A shortcut for {@link #mintBlessings(VContext, Activity, String, String, boolean)}} with
     * empty Google account, causing the user to be prompted to pick one of the installed Google
     * accounts (if there is more than one installed).
     */
    public static ListenableFuture<Blessings> mintBlessings(
            VContext ctx, Activity activity, final String key, boolean setAsDefault) {
        return mintBlessings(ctx, activity, key, "", setAsDefault);
    }

    public BlessingsManager() {}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBaseContext = V.init(getActivity());
        // onCreate() being called with non-null savedInstanceState is an indicator that the
        // fragment (and the containing activity) have been destroyed since originally
        // created, as onCreate() wouldn't be called again, otherwise.
        mWasDestroyed = savedInstanceState != null;
        if (!mWasDestroyed) {
            // Start the intent to fetch the blessings.
            ECPublicKey pubKey = V.getPrincipal(mBaseContext).publicKey();
            Intent intent = new Intent(getActivity(), BlessingActivity.class);
            intent.putExtra(BlessingActivity.EXTRA_PUBLIC_KEY, pubKey);
            if (mGoogleAccount != null && !mGoogleAccount.isEmpty()) {
                intent.putExtra(BlessingActivity.EXTRA_GOOGLE_ACCOUNT, mGoogleAccount);
            }
            intent.putExtra(BlessingActivity.EXTRA_PREF_KEY, mPrefKey);
            startActivityForResult(intent, REQUEST_CODE_MINT_BLESSINGS);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mBaseContext.cancel();
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        // Just write something into the bundle (see onCreate() above).
        savedInstanceState.putBoolean(STATE_SAVED, true);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_CODE_MINT_BLESSINGS: {
                if (mintFuture == null) {  // shouldn't really happen
                    break;
                }
                SettableFuture<Blessings> future = mintFuture;
                mintFuture = null;
                // Extract VOM-encoded blessings.
                if (data == null) {
                    future.setException(new VException("NULL blessing response"));
                    break;
                }
                if (resultCode != Activity.RESULT_OK) {
                    future.setException(new VException("Error getting blessing: " +
                            data.getStringExtra(BlessingActivity.EXTRA_ERROR)));
                    break;
                }
                byte[] blessingsVom = data.getByteArrayExtra(BlessingActivity.EXTRA_REPLY);
                if (blessingsVom == null || blessingsVom.length <= 0) {
                    future.setException(new VException("Got null blessings."));
                    break;
                }
                // VOM-Decode blessings.
                try {
                    Blessings blessings =
                            (Blessings) VomUtil.decode(blessingsVom, Blessings.class);
                    future.set(blessings);
                } catch (VException e) {
                    future.setException(e);
                }
                break;
            }
        }
        // Remove this fragment from the invoking activity.
        FragmentTransaction transaction = getActivity().getFragmentManager().beginTransaction();
        transaction.remove(this);
        transaction.commit();
        super.onActivityResult(requestCode, resultCode, data);
    }

    private static ListenableFuture<Blessings> wrapWithSetAsDefault(final VContext ctx,
            final Context context, ListenableFuture<Blessings> future) {
        return Futures.transform(future, new AsyncFunction<Blessings, Blessings>() {
            @Override
            public ListenableFuture<Blessings> apply(Blessings blessings) throws Exception {
                if (ctx.isCanceled()) {
                    return Futures.immediateFailedFuture(
                            new VException("Vanadium context canceled"));
                }
                // Update local state with the new blessings.
                try {
                    VPrincipal p = V.getPrincipal(ctx);
                    p.blessingStore().setDefaultBlessings(blessings);
                    p.blessingStore().set(blessings, Constants.ALL_PRINCIPALS);
                    VSecurity.addToRoots(p, blessings);
                    return Futures.immediateFuture(blessings);
                } catch (VException e) {
                    return Futures.immediateFailedFuture(e);
                }
            }
        });
    }
}
