// 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.baku.toolkit.blessings;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Base64;
import android.util.JsonReader;

import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.interfaces.ECPublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.v.android.v23.V;
import io.v.impl.google.naming.NamingUtil;
import io.v.v23.context.VContext;
import io.v.v23.security.BlessingPattern;
import io.v.v23.security.BlessingRoots;
import io.v.v23.security.Blessings;
import io.v.v23.security.CryptoUtil;
import io.v.v23.security.VPrincipal;
import io.v.v23.security.VSecurity;
import io.v.v23.security.access.AccessList;
import io.v.v23.security.access.Constants;
import io.v.v23.security.access.Permissions;
import io.v.v23.security.access.Tag;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
import java8.util.stream.Collectors;
import java8.util.stream.Stream;
import java8.util.stream.StreamSupport;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

/**
 * Common utilities for blessing and ACL management. In the future, we may want to factor these out
 * of Baku into the V23 Java libraries.
 */
@Slf4j
@UtilityClass
public class BlessingsUtils {
    public static final String
            PREF_BLESSINGS = "VanadiumBlessings",
            GLOBAL_BLESSING_ROOT_URL = "https://dev.v.io/auth/blessing-root";
    public static final Pattern DEV_V_IO_CLIENT_USER =
            Pattern.compile("dev\\.v\\.io:o:([^:]+):([^:]+).*");

    public static final AccessList OPEN_ACL = new AccessList(
            ImmutableList.of(new BlessingPattern("...")), ImmutableList.of());

    public static final ImmutableSet<Tag>
            DATA_TAGS = ImmutableSet.of(Constants.READ, Constants.WRITE, Constants.ADMIN),
            MOUNT_TAGS = ImmutableSet.of(Constants.READ, Constants.RESOLVE, Constants.ADMIN),
            SYNCGROUP_TAGS = ImmutableSet.of(Constants.READ, Constants.WRITE, Constants.RESOLVE,
                    Constants.ADMIN, Constants.DEBUG);

    public static final Permissions
            OPEN_DATA_PERMS = dataPermissions(OPEN_ACL),
            OPEN_MOUNT_PERMS = mountPermissions(OPEN_ACL);

    public static void writeSharedPrefs(final Context context, final Blessings blessings)
            throws VException {
        writeSharedPrefs(PreferenceManager.getDefaultSharedPreferences(context), PREF_BLESSINGS,
                blessings);
    }

    public static void writeSharedPrefs(final SharedPreferences prefs, final String key,
                                        final Blessings blessings) throws VException {
        prefs.edit().putString(key, VomUtil.encodeToString(blessings, Blessings.class)).apply();
    }

    public static Blessings readSharedPrefs(final Context context) throws VException {
        return readSharedPrefs(PreferenceManager.getDefaultSharedPreferences(context),
                PREF_BLESSINGS);
    }

    public static Blessings readSharedPrefs(final SharedPreferences prefs, final String key)
            throws VException {
        final String blessingsVom = prefs.getString(key, "");
        return Strings.isNullOrEmpty(blessingsVom) ? null : decodeBlessings(blessingsVom);
    }

    public static Blessings decodeBlessings(final String blessings) throws VException {
        return (Blessings) VomUtil.decodeFromString(blessings, Blessings.class);
    }

    public static Blessings decodeBlessings(final byte[] blessings) throws VException {
        return (Blessings) VomUtil.decode(blessings, Blessings.class);
    }

    public static Set<String> getBlessingNames(final VContext ctx, final Blessings blessings) {
        return ImmutableSet.copyOf(VSecurity.getBlessingNames(V.getPrincipal(ctx), blessings));
    }

    public static AccessList blessingsToAcl(final VContext ctx, final Blessings blessings) {
        return new AccessList(ImmutableList.copyOf(Collections2.transform(
                getBlessingNames(ctx, blessings),
                s -> new BlessingPattern(s))), //method reference confuses Android Studio
                ImmutableList.of());
    }

    /**
     * This method adds the given {@link BlessingPattern} to the given {@link AccessList} but does
     * not perform deduping or checking to make sure the new pattern is not in
     * {@link AccessList#getNotIn()}.
     */
    public static AccessList augmentAcl(final AccessList acl, final BlessingPattern newBlessing) {
        return new AccessList(ImmutableList.<BlessingPattern>builder()
                .addAll(acl.getIn())
                .add(newBlessing).build(),
                ImmutableList.of());
    }

    public static Stream<ClientUser> blessingsToClientUserStream(final VContext ctx,
                                                                 final Blessings blessings) {
        return StreamSupport.stream(getBlessingNames(ctx, blessings))
                .map(DEV_V_IO_CLIENT_USER::matcher)
                .filter(Matcher::matches)
                .map(m -> new ClientUser(m.group(1), m.group(2)));
    }

    /**
     * This method finds and parses all blessings of the form dev.v.io/o/....
     */
    public static Set<ClientUser> blessingsToClientUsers(
            final VContext ctx, final Blessings blessings) {
        return blessingsToClientUserStream(ctx, blessings).collect(Collectors.toSet());
    }

    public static String userMount(final String username) {
        return NamingUtil.join("users", username);
    }

    public static String clientMount(final String clientId) {
        return NamingUtil.join("tmp", "clients", clientId);
    }

    public static Stream<String> blessingsToClientMountStream(final VContext ctx,
                                                              final Blessings blessings) {
        return blessingsToClientUserStream(ctx, blessings)
                .map(cu -> BlessingsUtils.clientMount(cu.getClientId()));
    }

    public static Set<String> blessingsToClientMounts(final VContext ctx,
                                                      final Blessings blessings) {
        return blessingsToClientMountStream(ctx, blessings).collect(Collectors.toSet());
    }

    public static Permissions homogeneousPermissions(final Set<Tag> tags, final AccessList acl) {
        return new Permissions(Maps.toMap(Collections2.transform(tags, Tag::getValue), x -> acl));
    }

    public static Permissions dataPermissions(final AccessList acl) {
        return homogeneousPermissions(DATA_TAGS, acl);
    }

    public static Permissions mountPermissions(final AccessList acl) {
        return homogeneousPermissions(MOUNT_TAGS, acl);
    }

    public static Permissions syncgroupPermissions(final AccessList acl) {
        return homogeneousPermissions(SYNCGROUP_TAGS, acl);
    }

    /**
     * TODO(rosswang): This probably won't be best practice in the long run, but we'll need it until
     * we can bless the cloud Syncbase instance remotely.
     */
    public static Permissions cloudSyngroupPermissions(final AccessList userAcl,
                                                       final BlessingPattern sgHostBlessing) {
        final AccessList cloudAcl = augmentAcl(userAcl, sgHostBlessing);
        return new Permissions(ImmutableMap.of(
                Constants.ADMIN.getValue(), cloudAcl,
                Constants.READ.getValue(), cloudAcl,
                Constants.WRITE.getValue(), userAcl,
                Constants.RESOLVE.getValue(), userAcl,
                Constants.DEBUG.getValue(), userAcl
        ));
    }

    /**
     * Standard blessing handling for Vanadium applications:
     * <ul>
     * <li>Provide the given blessings when anybody connects to us.</li>
     * <li>Provide these blessings when we connect to other services (for example, when we talk
     * to the mounttable).</li>
     * <li>Trust these blessings and all the "parent" blessings.</li>
     * </ul>
     */
    public static void assumeBlessings(final VContext vContext, final Blessings blessings)
            throws VException {
        log.info("Assuming blessings: " + blessings);
        final VPrincipal principal = V.getPrincipal(vContext);
        principal.blessingStore().setDefaultBlessings(blessings);
        principal.blessingStore().set(blessings, new BlessingPattern("..."));
        VSecurity.addToRoots(principal, blessings);
    }

    public static void addGlobalBlessingRoots(final VContext vContext)
            throws IOException, VException {
        final URL url;
        try {
            url = new URL(GLOBAL_BLESSING_ROOT_URL);
        } catch (final MalformedURLException e) {
            throw new RuntimeException(e);
        }

        ECPublicKey publicKey = null;
        final List<BlessingPattern> names = new ArrayList<>();

        try (final JsonReader json = new JsonReader(
                new InputStreamReader(url.openStream(), StandardCharsets.US_ASCII))) {
            json.beginObject();
            while (json.hasNext()) {
                final String name = json.nextName();
                if ("publicKey".equals(name)) {
                    final String strKey = json.nextString();
                    final byte[] binKey = Base64.decode(strKey.getBytes(StandardCharsets.US_ASCII),
                            Base64.URL_SAFE);
                    publicKey = CryptoUtil.decodeECPublicKey(binKey);
                } else if ("names".equals(name)) {
                    json.beginArray();
                    while (json.hasNext()) {
                        names.add(new BlessingPattern(json.nextString()));
                    }
                    json.endArray();
                } else {
                    json.skipValue();
                }
            }
        }

        if (publicKey != null) {
            final BlessingRoots roots = V.getPrincipal(vContext).roots();
            for (final BlessingPattern name : names) {
                log.info("Adding global blessing root " + name);
                roots.add(publicKey, name);
            }
        } else {
            log.warn("No global blessing roots found");
        }
    }
}
