// Copyright 2016 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 examples.baku.io.permissions;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import examples.baku.io.permissions.util.Utils;


/**
 * Created by phamilton on 6/28/16.
 */
public class PermissionManager {

    public static final String EXTRA_TIMEOUT = "extraTimeout";
    public static final String EXTRA_COLOR = "extraColor";
    private DatabaseReference mDatabaseRef;
    private DatabaseReference mBlessingsRef;
    private DatabaseReference mRequestsRef;

    public static final int FLAG_DEFAULT = 0;
    public static final int FLAG_WRITE = 1 << 0;
    public static final int FLAG_READ = 1 << 1;

    static final String KEY_PERMISSIONS = "_permissions";
    static final String KEY_REQUESTS = "_requests";
    static final String KEY_BLESSINGS = "_blessings";

    private static final String KEY_ROOT = "root";

    private String mId;
    private Blessing rootBlessing;

    //<blessing id, blessing>
    private final Map<String, Blessing> mBlessings = new HashMap<>();
    //<source, target, blessing>
    private final Table<String, String, Blessing> mBlessingsTable = HashBasedTable.create();
    private final Set<String> mBlessingTargets = new HashSet();

    private final Map<String, PermissionRequest> mRequests = new HashMap<>();
    private final Table<String, String, PermissionRequest.Builder> mActiveRequests = HashBasedTable.create();

    private final Multimap<String, OnRequestListener> mRequestListeners = HashMultimap.create(); //<path,, >
    private final Multimap<String, OnRequestListener> mSubscribedRequests = HashMultimap.create(); //<request id, >

    private Blessing.PermissionTree mPermissionTree = new Blessing.PermissionTree();
    private final Multimap<String, OnPermissionChangeListener> mPermissionValueEventListeners = HashMultimap.create();
    private final Multimap<String, String> mNearestAncestors = HashMultimap.create();


    //TODO: replace string ownerId with Auth
    public PermissionManager(final DatabaseReference databaseReference, String owner) {
        this.mDatabaseRef = databaseReference;
        this.mId = owner;

        mRequestsRef = databaseReference.child(KEY_REQUESTS);
        //TODO: only consider requests from sources within the constellation
        mRequestsRef.addChildEventListener(requestListener);
        mBlessingsRef = mDatabaseRef.child(KEY_BLESSINGS);

        this.mId = owner;
        initRootBlessing();
        join(mId);

    }

    public void join(String group) {
        mBlessingsRef.orderByChild("target").equalTo(group).addChildEventListener(blessingListener);
        mBlessingTargets.add(group);
    }

    public void leave(String group) {
        mBlessingsRef.orderByChild("target").equalTo(group).removeEventListener(blessingListener);
        mBlessingTargets.remove(group);
    }

    public void initRootBlessing() {
        rootBlessing = Blessing.createRoot(this, mId);
    }

    //TODO: optimize this mess. Currently, recalculating entire permission tree.
    void refreshPermissions() {
        Blessing.PermissionTree updatedPermissionTree = new Blessing.PermissionTree();
        //received blessings
        for (Blessing blessing : getReceivedBlessings()) {
            if (blessing.isSynched()) {
                updatedPermissionTree.merge(blessing.getPermissionTree());
            }
        }

        //re-associate listeners with rules
        mNearestAncestors.clear();
        for (String path : mPermissionValueEventListeners.keySet()) {
            String nearestAncestor = Utils.getNearestCommonAncestor(path, updatedPermissionTree.keySet());
            if (nearestAncestor != null) {
                mNearestAncestors.put(nearestAncestor, path);
            }
        }

        Set<String> changedPermissions = new HashSet<>();

        //determine removed permissions
        Sets.SetView<String> removedPermissions = Sets.difference(mPermissionTree.keySet(), updatedPermissionTree.keySet());
        for (String path : removedPermissions) {
            String newPath = Utils.getNearestCommonAncestor(path, updatedPermissionTree.keySet());
            int previous = mPermissionTree.getPermissions(path);
            int current = updatedPermissionTree.getPermissions(newPath);
            if (previous != current) {
                changedPermissions.add(path);
            }
        }

        //compare previous tree
        for (Blessing.Permission permission : updatedPermissionTree.values()) {
            int previous = mPermissionTree.getPermissions(permission.path);
            int current = updatedPermissionTree.getPermissions(permission.path);
            if (previous != current) {
                changedPermissions.add(permission.path);
            }
        }

        mPermissionTree = updatedPermissionTree;

        //notify listeners
        for (String path : changedPermissions) {
            onPermissionsChange(path);
        }
    }

    //call all the listeners effected by a permission change at this path
    void onPermissionsChange(String path) {
        int permission = getPermissions(path);
        if (mNearestAncestors.containsKey(path)) {
            for (String listenerPath : mNearestAncestors.get(path)) {
                if (mPermissionValueEventListeners.containsKey(listenerPath)) {
                    for (OnPermissionChangeListener listener : mPermissionValueEventListeners.get(listenerPath)) {
                        listener.onPermissionChange(permission);
                    }
                }
            }
        }
    }


    public Set<PermissionRequest> getRequests(String path) {
        Set<PermissionRequest> result = new HashSet<>();
        for (PermissionRequest request : mRequests.values()) {
            if (getAllPaths(request.getPath()).contains(path)) {
                result.add(request);
            }
        }
        return result;
    }

    public PermissionRequest getRequest(String rId) {
        return mRequests.get(rId);
    }


    public Blessing getRootBlessing() {
        return rootBlessing;
    }

    public Set<Blessing> getReceivedBlessings() {
        Set<Blessing> result = new HashSet<>();
        for (String target : mBlessingTargets) {
            result.addAll(mBlessingsTable.column(target).values());
        }
        return result;
    }

    public Set<Blessing> getGrantedBlessings(String src) {
        return new HashSet<>(mBlessingsTable.row(src).values());
    }

    public Blessing putBlessing(Blessing blessing) {
        String source = blessing.getSource();
        String target = blessing.getTarget();
        mBlessings.put(blessing.getId(), blessing);
        if (source == null) {
            source = KEY_ROOT;
        }
        return mBlessingsTable.put(source, target, blessing);
    }

    public Blessing getBlessing(String id) {
        return mBlessings.get(id);
    }

    public Blessing getBlessing(String source, String target) {
        if (source == null) {
            source = KEY_ROOT;
        }
        return mBlessingsTable.get(source, target);
    }

    public void removeBlessing(String rId) {
        Blessing removedBlessing = mBlessings.remove(rId);
        if (removedBlessing != null) {
            mBlessingsTable.remove(removedBlessing.getSource(), removedBlessing.getTarget());

        }
    }

    //return a blessing interface for granting/revoking permissions
    //uses local device blessing as root
    public Blessing bless(String target) {
        return rootBlessing.bless(target);
    }

    public DatabaseReference getBlessingsRef() {
        return mBlessingsRef;
    }

    private ChildEventListener requestListener = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            onRequestUpdated(dataSnapshot);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            onRequestUpdated(dataSnapshot);
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            onRequestRemoved(dataSnapshot);
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    public void finishRequest(String rId) {
        //TODO: notify source entity and ignore instead of removing
        mRequestsRef.child(rId).removeValue();
    }

    public void grantRequest(PermissionRequest request) {
        Blessing blessing = bless(request.getSource());
        blessing.setPermissions(request.getPath(), request.getPermissions());
        finishRequest(request.getId());
    }

    private void onRequestUpdated(DataSnapshot snapshot) {
        if (!snapshot.exists()) {
            return;
        }

        PermissionRequest request = snapshot.getValue(PermissionRequest.class);
        if (request == null) {
            return;
        }

        String requestPath = request.getPath();
        if (requestPath == null) {
            return;
        }

        //ignore local requests
        if (mId.equals(request.getSource())) {
            return;
        }

        //Check if request permissions can be granted by this instance
        if ((getPermissions(requestPath) & request.getPermissions()) != request.getPermissions()) {
            return;
        }

        String rId = request.getId();
        String source = request.getSource();
        mRequests.put(rId, request);

        if (mSubscribedRequests.containsKey(rId)) {
            for (OnRequestListener listener : new HashSet<>(mSubscribedRequests.get(rId))) {
                if (!listener.onRequest(request, bless(source))) {
                    //cancel subscription
                    mSubscribedRequests.remove(rId, listener);
                }
            }
        } else {
            for (String path : getAllPaths(request.getPath())) {
                for (OnRequestListener listener : mRequestListeners.get(path)) {
                    if (listener.onRequest(request, bless(source))) {
                        //add subscription
                        mSubscribedRequests.put(request.getId(), listener);
                    }
                }
            }
        }
    }

    private void onRequestRemoved(DataSnapshot snapshot) {
        mRequests.remove(snapshot.getKey());
        PermissionRequest request = snapshot.getValue(PermissionRequest.class);
        String source = request.getSource();
        if (request != null && !mId.equals(source)) {    //ignore local requests
            for (OnRequestListener listener : mSubscribedRequests.removeAll(request.getId())) {
                listener.onRequestRemoved(request, bless(source));
            }
        }
    }

    //allows
    private Set<String> getAllPaths(String path) {
        Set<String> result = new HashSet<>();
        result.add(path);
        result.add("*");
        String subpath = path;
        int index;
        while ((index = subpath.lastIndexOf("/")) != -1) {
            subpath = subpath.substring(0, index);
            result.add(subpath + "/*");
        }
        return result;
    }

    private ChildEventListener blessingListener = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot snapshot, String s) {
            Blessing receivedBlessing = Blessing.fromSnapshot(PermissionManager.this, snapshot);
            receivedBlessing.addListener(blessingChangedListner);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            Blessing removedBlessing = mBlessings.remove(dataSnapshot.getKey());
            if (removedBlessing != null) {
                removedBlessing.removeListener(blessingChangedListner);
                mBlessingsTable.remove(removedBlessing.getSource(), removedBlessing.getTarget());
                refreshPermissions();
            }
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    private Blessing.OnBlessingUpdatedListener blessingChangedListner = new Blessing.OnBlessingUpdatedListener() {
        @Override
        public void onBlessingUpdated(Blessing blessing) {
            refreshPermissions();
        }

        @Override
        public void onBlessingRemoved(Blessing blessing) {
            refreshPermissions();
        }
    };


    public int getPermissions(String path) {
        return mPermissionTree.getPermissions(path);
    }

    public OnPermissionChangeListener addPermissionEventListener(String path, OnPermissionChangeListener listener) {
        int current = FLAG_DEFAULT;
        mPermissionValueEventListeners.put(path, listener);

        String nearestAncestor = Utils.getNearestCommonAncestor(path, mPermissionTree.keySet());
        if (nearestAncestor != null) {
            current = getPermissions(nearestAncestor);
            mNearestAncestors.put(nearestAncestor, path);
        }
        listener.onPermissionChange(current);
        return listener;
    }

    public void removePermissionEventListener(String path, OnPermissionChangeListener listener) {
        mPermissionValueEventListeners.remove(path, listener);
        String nca = Utils.getNearestCommonAncestor(path, mPermissionTree.keySet());
        mNearestAncestors.remove(nca, path);

    }


    public void removeOnRequestListener(String path, OnRequestListener requestListener) {
        mRequestListeners.remove(path, requestListener);
        if (mRequestListeners.values().contains(requestListener)) {
            //TODO: this doesn't catch cases where one request listener unsubscribed
            for (Map.Entry<String, OnRequestListener> entry : mSubscribedRequests.entries()) {
                if (entry.getValue().equals(requestListener)) {
                    String rId = entry.getKey();
                    PermissionRequest request = mRequests.get(rId);
                    if (getAllPaths(request.getPath()).contains(path)) {
                        mSubscribedRequests.remove(rId, requestListener);
                    }
                }
            }

        } else {
            mSubscribedRequests.values().remove(requestListener);
        }
    }

    public OnRequestListener addOnRequestListener(String path, OnRequestListener requestListener) {
        mRequestListeners.put(path, requestListener);
        for (Map.Entry<String, PermissionRequest> entry : mRequests.entrySet()) {
            String rId = entry.getKey();
            PermissionRequest request = entry.getValue();
            Set<String> requestPaths = getAllPaths(request.getPath());
            if (requestPaths.contains(path)) {
                String source = request.getSource();
                if (requestListener.onRequest(request, bless(source))) {
                    mSubscribedRequests.put(rId, requestListener);
                }
            }
        }
        return requestListener;
    }

    public PermissionRequest.Builder request(String path, String group) {
        PermissionRequest.Builder builder = mActiveRequests.get(group, path);
        if (builder == null) {
            builder = new PermissionRequest.Builder(mRequestsRef.push(), path, mId);
            mActiveRequests.put(group, path, builder);
        }
        return builder;
    }

    public void cancelRequests(String group) {
        Collection<PermissionRequest.Builder> builders = mActiveRequests.row(group).values();
        for (PermissionRequest.Builder builder : builders) {
            builder.cancel();
        }
        builders.clear();
    }

    public void cancelRequest(String group, String path) {
        PermissionRequest.Builder builder = mActiveRequests.remove(group, path);
        if (builder != null) {
            builder.cancel();
        }
    }

    public void onDestroy() {
        mBlessingsRef.removeEventListener(blessingListener);
        mRequestsRef.removeEventListener(requestListener);
        for (Blessing blessing : new HashSet<Blessing>(mBlessings.values())) {
            blessing.revoke();
        }
    }

    public interface OnRequestListener {
        boolean onRequest(PermissionRequest request, Blessing blessing);

        void onRequestRemoved(PermissionRequest request, Blessing blessing);
    }

    public interface OnPermissionChangeListener {
        void onPermissionChange(int current);

        void onCancelled(DatabaseError databaseError);
    }
}
