// 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.UnmodifiableIterator;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.ValueEventListener;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;

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

/**
 * Created by phamilton on 7/9/16.
 */
public class Blessing implements Iterable<Blessing.Permission>, ValueEventListener {

    private static final String KEY_PERMISSIONS = "_permissions";
    private static final String KEY_RULES = "rule";

    private PermissionManager permissionManager;

    private String id;
    private String source;
    private String target;
    private DatabaseReference ref;
    private DatabaseReference rulesRef;
    private DataSnapshot snapshot;

    private Blessing parentBlessing;
    private final Map<String, Integer> permissions = new HashMap<>();
    private final PermissionTree permissionTree = new PermissionTree();

    private final Set<OnBlessingUpdatedListener> blessingListeners = new HashSet<>();


    public interface OnBlessingUpdatedListener {
        void onBlessingUpdated(Blessing blessing);

        void onBlessingRemoved(Blessing blessing);
    }

    private Blessing(PermissionManager permissionManager, String id, String source, String target) {
        this.permissionManager = permissionManager;
        if (id == null) {
//            setRef(permissionManager.getBlessingsRef().push());
            //TEMP: use a combination of source and target for debugging
            setRef(permissionManager.getBlessingsRef().child(source + "_" + target));
            id = this.ref.getKey();

        } else {
            setRef(permissionManager.getBlessingsRef().child(id));
        }
        setId(id);
        setSource(source);
        setTarget(target);
    }

    public static Blessing create(PermissionManager permissionManager, String id, String source, String target) {
        Blessing blessing = permissionManager.getBlessing(source, target);
        if (blessing == null) {
            blessing = new Blessing(permissionManager, id, source, target);
            permissionManager.putBlessing(blessing);
        }
        return blessing;
    }

    //root blessings have no source blessing and their id is the same as their target
    public static Blessing createRoot(PermissionManager permissionManager, String target) {
        return create(permissionManager,target, null, target);
    }

    public static Blessing fromSnapshot(PermissionManager permissionManager, DataSnapshot snapshot) {
        String id = snapshot.getKey();
        String target = snapshot.child("target").getValue(String.class);
        String source = null;
        if (snapshot.hasChild("source"))
            source = snapshot.child("source").getValue(String.class);
        return create(permissionManager,id, source, target);
    }

    public OnBlessingUpdatedListener addListener(OnBlessingUpdatedListener listener) {
        blessingListeners.add(listener);
        listener.onBlessingUpdated(this);
        return listener;
    }

    public boolean addListeners(Collection<OnBlessingUpdatedListener> listeners) {
        return this.blessingListeners.addAll(listeners);
    }

    public boolean removeListener(OnBlessingUpdatedListener listener) {
        return blessingListeners.remove(listener);
    }

    public boolean removeListeners(Collection<OnBlessingUpdatedListener> listeners) {
        return blessingListeners.removeAll(listeners);
    }

    private final OnBlessingUpdatedListener parentListener = new OnBlessingUpdatedListener() {
        @Override
        public void onBlessingUpdated(Blessing blessing) {
            permissionTree.parentTree = parentBlessing.permissionTree;
            notifyListeners();
        }

        @Override
        public void onBlessingRemoved(Blessing blessing) {
            //revoke self
            revoke();
        }
    };

    public boolean isSynched() {
        return snapshot != null;
    }

    public String getId() {
        return id;
    }

    public String getSource() {
        return source;
    }

    public String getTarget() {
        return target;
    }

    public void setId(String id) {
        this.id = id;
        ref.child("id").setValue(id);
    }

    private void setSource(String source) {
        if (this.source == null && source != null) {
            this.source = source;
            ref.child("source").setValue(source);
            parentBlessing = permissionManager.getBlessing(source);
            if (parentBlessing == null) { //retrieve, if manager isn't tracking blessing
                permissionManager.getBlessingsRef().child(source).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot.exists()) {
                            parentBlessing = Blessing.fromSnapshot(permissionManager, dataSnapshot);
                            parentBlessing.addListener(parentListener);
                        } else {  //destroy self if source doesn't exist
                            revoke();
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
            } else {
                permissionTree.parentTree = parentBlessing.permissionTree;
                parentBlessing.addListener(parentListener);
            }
        }
    }

    private void notifyListeners() {
        for (OnBlessingUpdatedListener listener : blessingListeners) {
            listener.onBlessingUpdated(this);
        }
    }

    public void setTarget(String target) {
        this.target = target;
        ref.child("target").setValue(target);
    }

    private void setSnapshot(DataSnapshot snapshot) {
        if (!snapshot.exists()) {
            throw new IllegalArgumentException("empty snapshot");
        }
        this.snapshot = snapshot;
        if (snapshot.hasChild(KEY_RULES)) {
            this.permissionTree.setRoot(new Permission(snapshot.child(KEY_RULES), null, 0));
        } else {
            this.permissionTree.setRoot(new Permission());
        }
    }

    public Blessing setPermissions(String path, int permissions) {
        this.permissions.put(path, permissions);
        getRef(path).setPermission(permissions);
        return this;
    }

    public void setPermissions(Map<String, Integer> permissions) {
        for (Map.Entry<String, Integer> entry : permissions.entrySet()) {
            setPermissions(entry.getKey(), permissions.get(entry.getValue()));
        }
    }

    public Blessing clearPermissions(String path) {
        getRef(path).clearPermission();
        this.permissions.remove(path);
        return this;
    }

    public Blessing revoke() {
        if (parentBlessing != null) {
            parentBlessing.removeListener(parentListener);
        }
        for (OnBlessingUpdatedListener listener : blessingListeners) {
            listener.onBlessingRemoved(this);
        }
        ref.removeEventListener(this);
        rulesRef.removeValue();
        return this;
    }

    //delete all permission above path
    public Blessing revokePermissions(String path) {
        if (path != null) {
            rulesRef.child(path).removeValue();
        } else {
            rulesRef.removeValue();
        }
        return this;
    }

    private PermissionReference getRef(String path) {
        return new PermissionReference(rulesRef, path);
    }

    private void setRef(DatabaseReference ref) {
        this.ref = ref;
        this.rulesRef = ref.child(KEY_RULES);

        ref.addValueEventListener(this);
    }

    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.exists()) {
            setSnapshot(dataSnapshot);
            notifyListeners();
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        databaseError.toException().printStackTrace();
    }

    //return a blessing interface for granting/revoking permissions
    public Blessing bless(String target) {
        Blessing result = getBlessing(target);
        if (result == null) {
            if (isDescendantOf(target) || target.equals(this.target)) {
                throw new IllegalArgumentException("Can't bless a target that already exists in the blessing hiearchy.");
            }
            result = Blessing.create(permissionManager, null, getId(), target);
        }
        return result;
    }

    public Blessing getBlessing(String target) {
        return permissionManager.getBlessing(getId(), target);
    }

    public boolean isDescendantOf(String target) {
        return this.target.equals(target) || parentBlessing != null && parentBlessing.isDescendantOf(target);
    }

    @Override
    public Iterator<Permission> iterator() {
        return isSynched() ? permissionTree.iterator() : null;
    }

    public PermissionTree getPermissionTree() {
        return permissionTree;
    }

    public static class Permission implements Iterable<Permission> {
        String key;
        String path;
        int inherited;
        int permissions;
        final Map<String, Permission> children = new HashMap();


        public Permission() {
        }

        public Permission(DataSnapshot snapshot, String path, int inherited) {
            this.path = path;
            if (path != null) {
                this.key = snapshot.getKey();
            }
            this.inherited = inherited;
            if (snapshot.hasChild(KEY_PERMISSIONS)) {
                this.permissions |= snapshot.child(KEY_PERMISSIONS).getValue(Integer.class);
            }
            for (DataSnapshot child : snapshot.getChildren()) {
                if (child.getKey().startsWith("_")) { //ignore keys with '_' prefix
                    continue;
                }
                String childPath = child.getKey();
                if (path != null) {
                    childPath = path + "/" + childPath;
                }
                children.put(child.getKey(), new Permission(child, childPath, this.permissions | this.inherited));
            }
        }

        public Permission copy() {
            Permission result = new Permission();
            result.key = key;
            result.path = path;
            result.inherited = inherited;
            result.permissions = permissions;
            for (Permission child : children.values()) {
                result.children.put(child.key, child.copy());
            }
            return result;
        }

        public void addPermissions(int permission) {
            this.permissions |= permission;
            for (Permission child : children.values()) {
                child.setInherited(getPermissions());
            }
        }

        public void setInherited(int permission) {
            if (this.inherited != permission) {
                this.inherited = permission;
                propagateInherited();
            }
        }

        public void propagateInherited() {
            for (Permission child : children.values()) {
                child.setInherited(getPermissions());
            }
        }

        public void removePermissions(int permission) {
            this.permissions &= ~(permission);
            propagateInherited();
        }

        public void checkPermissions(int reference) {
            this.permissions &= reference;
            propagateInherited();
        }

        public void checkPermissions(PermissionTree ref) {
            for (Permission permission : this) {
                permission.permissions &= ref.getPermissions(permission.path);
            }
            setInherited(inherited & ref.getPermissions(path));
        }


        public Permission child(String path) {
            int index = path.indexOf("/");
            if (index != -1) {
                return this.children.get(path);
            }
            Permission child = this.children.get(path.substring(0, index));
            if (child != null && path.length() - index > 1) {
                return child.child(path.substring(index));
            }
            return null;
        }


        public int getPermissions() {
            return permissions | inherited;
        }


        @Override
        public Iterator<Permission> iterator() {
            final Stack<Permission> nodeStack = new Stack<>();
            nodeStack.push(this);

            final Stack<String> pathStack = new Stack<>();
            pathStack.push(null); //default rule

            return new UnmodifiableIterator<Permission>() {
                @Override
                public boolean hasNext() {
                    return !nodeStack.isEmpty();
                }

                @Override
                public Permission next() {
                    Permission node = nodeStack.pop();
                    for (final Permission child : node.children.values()) {
                        nodeStack.push(child);
                    }
                    return node;
                }
            };
        }
    }


    public static class PermissionTree implements Iterable<Permission> {
        Permission root;
        final Map<String, Permission> rules = new HashMap<>();
        PermissionTree parentTree;

        public PermissionTree(DataSnapshot snapshot) {
            setRoot(new Permission(snapshot, null, 0));
        }

        public PermissionTree() {
            setRoot(new Permission());
        }

        public void setRoot(Permission root) {
            this.root = root;
            updateRules();
        }

        public void merge(PermissionTree tree) {
            Permission permissionA;
            Permission permissionB = tree.root;
            permissionB.checkPermissions(tree);   //check no permissions exceed parent
            Queue<Permission> permissionQueue = new LinkedList<>();
            permissionQueue.add(permissionB);

            while (!permissionQueue.isEmpty()) {
                permissionB = permissionQueue.remove();
                permissionA = rules.get(permissionB.path);
                permissionA.addPermissions(tree.getPermissions(permissionB.path));
                for (Permission child : permissionB.children.values()) {
                    if (rules.containsKey(child.path)) {
                        permissionQueue.add(child);
                    } else {
                        Permission childCopy = child.copy();
                        childCopy.setInherited(permissionA.getPermissions());
                        permissionA.children.put(childCopy.key, childCopy);
                    }
                }
            }
            updateRules();
        }

        private void updateRules() {
            rules.clear();
            for (Permission permission : root) {
                rules.put(permission.path, permission);
            }
        }

        public Permission get(String path) {
            return rules.get(path);
        }

        public int getPermissions(String path) {
            path = Utils.getNearestCommonAncestor(path,keySet());
            Permission permission = get(path);
            if (permission == null) {
                return 0;
            }
            int result = permission.getPermissions();
            if (parentTree != null) { //validate
                result &= parentTree.getPermissions(path);
            }
            return result;
        }

        public Set<String> keySet() {
            return rules.keySet();
        }

        public Collection<Permission> values() {
            return rules.values();
        }

        @Override
        public Iterator<Permission> iterator() {
            return root.iterator();
        }
    }
}
