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

import io.v.v23.context.VContext;
import io.v.v23.uniqueid.Id;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * A singleton global registry that maps the unique ids of caveats to their validators.
 * <p>
 * It is safe to invoke methods on {@link CaveatRegistry} concurrently.
 */
public class CaveatRegistry {
    private static final Map<Id, RegistryEntry> validators = new HashMap<Id, RegistryEntry>();
    private static final ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * Associates a caveat descriptor with the validator that is used for validating
     * all caveats with the same identifier as the descriptor.
     * <p>
     * This method may be called at most once per unique identifier and will throw an exception
     * on duplicate registrations.
     *
     * @param  desc        caveat descriptor
     * @param  validator   caveat validator
     * @throws VException  if the given caveat validator and descriptor couldn't be registered
     */
    public static void register(CaveatDescriptor desc, CaveatValidator validator)
            throws VException {
        String registerer = getRegisterer();
        lock.writeLock().lock();
        RegistryEntry existing = validators.get(desc.getId());
        if (existing != null) {
            lock.writeLock().unlock();
            throw new VException(String.format("Caveat with UUID %s registered twice. " +
                "Once with (%s, validator=%s) from %s, once with (%s, validator=%s) from %s",
                desc.getId(), existing.getDescriptor().getParamType(), existing.getValidator(),
                existing.getRegisterer(), desc.getParamType(), validator, registerer));
        }
        // TODO(spetrovic): Once rogulenko@ is done, get the Type from desc.getParamType().
        Type paramType = null;
        RegistryEntry entry = new RegistryEntry(desc, validator, paramType, registerer);
        validators.put(desc.getId(), entry);
        lock.writeLock().unlock();
    }

    /**
     * Throws an exception iff the restriction encapsulated in the corresponding caveat
     * hasn't been satisfied given the context.
     *
     * @param  context     a vanadium context
     * @param  caveat      security caveat
     * @throws VException  if the caveat couldn't be validated
     */
    public static void validate(VContext context, Call call, Caveat caveat) throws VException {
        RegistryEntry entry = lookup(caveat.getId());
        if (entry == null) {
            throw Errors.newCaveatNotRegistered(null, caveat.getId());
        }
        Object param = null;
        try {
            // TODO(spetrovic): Once rogulenko@ is done, decode with entry.getParamType().
            param = VomUtil.decode(caveat.getParamVom());
        } catch (VException e) {
            throw new VException(e.getMessage());
        }
        // TODO(spetrovic): Once rogulenko@ is done, pass the type as well.
        entry.validator.validate(context, call, param);
    }

    private static RegistryEntry lookup(Id id) {
        lock.readLock().lock();
        RegistryEntry entry = validators.get(id);
        lock.readLock().unlock();
        return entry;
    }

    private static String getRegisterer() {
        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        if (stack == null || stack.length < 2) {
            return "";
        }
        StackTraceElement registerer = stack[stack.length - 2];
        return String.format("%s:%d", registerer.getFileName(), registerer.getLineNumber());
    }

    private static class RegistryEntry {
        CaveatDescriptor desc;
        CaveatValidator validator;
        Type paramType;
        String registerer;

        RegistryEntry(CaveatDescriptor desc,
                CaveatValidator validator, Type paramType, String registerer) {
            this.desc = desc;
            this.validator = validator;
            this.paramType = paramType;
            this.registerer = registerer;
        }
        CaveatDescriptor getDescriptor() { return this.desc; }
        CaveatValidator getValidator() { return this.validator; }
        @SuppressWarnings("unused")
        Type getParamType() { return this.paramType; }
        String getRegisterer() { return this.registerer; }
    }

    private CaveatRegistry() {}
}
