// 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.v23.syncbase.util;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.Ordering;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.v.impl.google.naming.NamingUtil;
import io.v.v23.InputChannel;
import io.v.v23.InputChannels;
import io.v.v23.V;
import io.v.v23.VFutures;
import io.v.v23.context.VContext;
import io.v.v23.naming.GlobReply;
import io.v.v23.security.access.AccessList;
import io.v.v23.security.access.Permissions;
import io.v.v23.security.access.Tag;
import io.v.v23.services.syncbase.CollectionRowPattern;
import io.v.v23.services.syncbase.Id;
import io.v.v23.verror.VException;

import java.io.UnsupportedEncodingException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import javax.annotation.CheckReturnValue;

/**
 * Various NoSQL utility methods.
 */
public class Util {
    private Util() {
    }

    /**
     * Encodes a component name for use in a Syncbase object name. In
     * particular, it replaces bytes {@code "%"} and {@code "/"} with the
     * {@code "%"} character followed by the byte's two-digit hex code. Clients
     * using the client library need not encode names themselves; the client
     * library does so on their behalf.
     *
     * @param s String to encode.
     * @return Encoded string.
     */
    public static String encode(String s) {
        return NamingUtil.encodeAsNameElement(s);
    }

    /**
     * Applies the inverse of {@link Util#encode}. Throws exception if the given string is
     * not a valid encoded string.
     *
     * @param s String to decode.
     * @return Decoded string.
     * @throws IllegalArgumentException if {@code s} is truncated or malformed.
     */
    public static String decode(String s) {
        return NamingUtil.decodeFromNameElement(s);
    }

    /**
     * EncodeId encodes the given Id for use in a Syncbase object name.
     *
     * @param id Id to encode.
     * @return Encoded string.
     */
    public static String encodeId(Id id) {
        // Note that "," is not allowed to appear in blessing patterns. We also
        // could've used "/" as a separator, but then we would've had to be more
        // careful with decoding and splitting name components elsewhere.
        return encode(id.getBlessing() + "," + id.getName());
    }

    /**
     * Applies the inverse of {@link Util#encodeId}. Throws exception if the given string is
     * not a valid encoded string.
     *
     * @param s String to decode.
     * @return Decoded string.
     * @throws IllegalArgumentException if {@code s} is truncated or malformed.
     */
    public static Id decodeId(String s) throws VException {
        String decoded = decode(s);
        String[] parts = decoded.split(",", 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("Failed to decode id: " + s);
        }
        Id id = new Id(parts[0], parts[1]);
        return id;
    }

    /**
     * Character used for escaping wildcards in LIKE-style patterns ('%', '_', and itself).
     */
    public static final char EscapeChar = '\\';

    /**
     * Escapes the given string for inclusion as a literal in a LIKE-style pattern.
     * It inserts '\' before each '_', '%', and '\' in the string.
     *
     * @param s String to escape.
     * @return String with all wildcards escaped.
     */
    public static String escapePattern(String s) {
        // Replace each literal '\', '%', and '_' with a literal '\' plus the matched character.
        return s.replaceAll("[\\\\%_]", "\\\\$0");
    }

    /**
     * Returns a CollectionRowPattern matching a single key prefix in a single collection.
     *
     * @param cxId      Collection to match.
     * @param keyPrefix Key prefix to match.
     * @return CollectionRowPattern matching the specified prefix in the specified collection.
     */
    public static CollectionRowPattern rowPrefixPattern(Id cxId, String keyPrefix) {
        return new CollectionRowPattern(
            escapePattern(cxId.getBlessing()),
            escapePattern(cxId.getName()),
            escapePattern(keyPrefix) + "%");
    }

    /**
     * Returns the start of the row range for the given prefix.
     */
    public static String prefixRangeStart(String prefix) {
        return prefix;
    }

    /**
     * Returns the limit of the row range for the given prefix.
     */
    public static String prefixRangeLimit(String prefix) {
        // We convert a string to a byte[] array, which can be thought of as a base-256
        // number.  The code below effectively adds 1 to this number, then chops off any
        // trailing 0x00 bytes. If the input string consists entirely of 0xFF, an empty string
        // will be returned.
        try {
            byte[] bytes = prefix.getBytes("ISO8859-1");
            int last = bytes.length - 1;
            for (; last >= 0 && bytes[last] == (byte) 0xFF; --last) ;
            if (last < 0) {
                return "";
            }
            bytes[last] += 1;
            return new String(bytes, 0, last + 1, "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("JVM must support ISO8859-1 char encoding", e);
        }
    }

    /**
     * Returns a new {@link ListenableFuture} whose result are the relative names of all children
     * of {@code parentFullName}.
     * <p>
     * The returned future is guaranteed to be executed on an {@link java.util.concurrent.Executor}
     * specified in {@code context} (see {@link V#withExecutor}).
     * <p>
     * The returned future will fail with {@link java.util.concurrent.CancellationException} if
     * {@code context} gets canceled.
     *
     * @param context        Vanadium context
     * @param parentFullName object name of parent component
     */
    @CheckReturnValue
    public static ListenableFuture<List<Id>> listChildIds(
            VContext context, String parentFullName) {
        InputChannel<GlobReply> input =
                V.getNamespace(context).glob(context, NamingUtil.join(parentFullName, "*"));
        return VFutures.withUserLandChecks(context,
                Futures.transform(InputChannels.asList(InputChannels.transform(context, input,
                        new InputChannels.TransformFunction<GlobReply, Id>() {
                            @Override
                            public Id apply(GlobReply from) throws VException {
                                return idFromGlobReply(from);
                            }
                        })), new Function<List<Id>, List<Id>>() {
                    @Override
                    public List<Id> apply(List<Id> input) {
                        return Ordering.from(new IdComparator())
                                .immutableSortedCopy(input);
                    }
                }));
    }

    private static Id idFromGlobReply(GlobReply reply) throws VException {
        if (reply instanceof GlobReply.Entry) {
            String fullName = ((GlobReply.Entry) reply).getElem().getName();
            int idx = fullName.lastIndexOf('/');
            if (idx == -1) {
                throw new VException("Unexpected glob() reply name: " + fullName);
            }
            String encName = fullName.substring(idx + 1, fullName.length());
            // Component names within object names are always encoded.
            // See comment in server/nosql/dispatcher.go for
            // explanation. If decode throws an exception, there's a
            // bug in the Syncbase server. Glob should return names with
            // encoded components.
            return decodeId(encName);
        } else if (reply instanceof GlobReply.Error) {
            // TODO(sadovsky): Surface these errors somehow. (We don't
            // want to throw an exception, since some names may simply
            // be hidden to this client.)
            return null;
        } else if (reply == null) {
            throw new VException("null glob() reply");
        } else {
            throw new VException("Unrecognized glob() reply type: " + reply.getClass());
        }
    }

    /**
     * Returns the UTF-8 encoding of the provided string.
     */
    public static byte[] getBytes(String s) {
        if (s == null) {
            s = "";
        }
        return s.getBytes(Charsets.UTF_8);
    }

    /**
     * Returns the UTF-8 decoded string.
     */
    public static String getString(byte[] bytes) {
        return new String(bytes, Charsets.UTF_8);
    }

    /**
     * Returns the app blessing obtained from the context.
     */
    public static String AppBlessingFromContext(VContext ctx) {
        // TODO(ivanpi,sadovsky): Hook up the Go implementation through the new
        // Cgo bridge. For now, Java clients must provide explicit id blessings
        // and perms.
        // TODO(ivanpi): Add id blessing and perms inference tests when this is
        // fixed.
        return "v.io:a:xyz";
    }

    /**
     * Returns the user blessing obtained from the context.
     */
    public static String UserBlessingFromContext(VContext ctx) {
        // TODO(ivanpi,sadovsky): Hook up the Go implementation through the new
        // Cgo bridge. For now, Java clients must provide explicit id blessings
        // and perms.
        // TODO(ivanpi): Add id blessing and perms inference tests when this is
        // fixed.
        return "v.io:u:sam";
    }

    /**
     * Returns a filtered copy of the given permissions, only including the tags specified.
     */
    public static Permissions filterPermissionsByTags(Permissions perms, Iterable<Tag> tags) {
        Permissions filtered = new Permissions();
        for (Tag tag: tags) {
            String tagStr = tag.getValue();
            AccessList acl = perms.get(tagStr);
            if (acl != null) {
                AccessList aclCopy = new AccessList(new ArrayList<>(acl.getIn()),
                        new ArrayList<>(acl.getNotIn()));
                filtered.put(tagStr, aclCopy);
            }
        }
        return filtered;
    }

    /**
     * Compares two Syncbase Ids.
     * Blessing is compared first and then the name.
     */
    private static class IdComparator implements Comparator<Id> {
        @Override
        public int compare(Id a, Id b) {
            final Collator collator = Collator.getInstance();
            if (a.getBlessing() != b.getBlessing()) {
                return collator.compare(a.getBlessing(), b.getBlessing());
            } else {
                return collator.compare(a.getName(), b.getName());
            }
        }
    }

}

