/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.spi.security.privilege;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.google.common.primitives.Longs;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Internal representation of JCR privileges.
 */
public final class PrivilegeBits implements PrivilegeConstants {

    private static final long NO_PRIVILEGE = 0;
    private static final long READ_NODES = 1;
    private static final long READ_PROPERTIES = READ_NODES << 1;
    private static final long ADD_PROPERTIES = READ_PROPERTIES << 1;
    private static final long ALTER_PROPERTIES = ADD_PROPERTIES << 1;
    private static final long REMOVE_PROPERTIES = ALTER_PROPERTIES << 1;
    private static final long ADD_CHILD_NODES = REMOVE_PROPERTIES << 1;
    private static final long REMOVE_CHILD_NODES = ADD_CHILD_NODES << 1;
    private static final long REMOVE_NODE = REMOVE_CHILD_NODES << 1;
    private static final long READ_AC = REMOVE_NODE << 1;
    private static final long MODIFY_AC = READ_AC << 1;
    private static final long NODE_TYPE_MNGMT = MODIFY_AC << 1;
    private static final long VERSION_MNGMT = NODE_TYPE_MNGMT << 1;
    private static final long LOCK_MNGMT = VERSION_MNGMT << 1;
    private static final long LIFECYCLE_MNGMT = LOCK_MNGMT << 1;
    private static final long RETENTION_MNGMT = LIFECYCLE_MNGMT << 1;
    private static final long WORKSPACE_MNGMT = RETENTION_MNGMT << 1;
    private static final long NODE_TYPE_DEF_MNGMT = WORKSPACE_MNGMT << 1;
    private static final long NAMESPACE_MNGMT = NODE_TYPE_DEF_MNGMT << 1;
    private static final long PRIVILEGE_MNGMT = NAMESPACE_MNGMT << 1;
    private static final long USER_MNGMT = PRIVILEGE_MNGMT << 1;
    private static final long INDEX_DEFINITION_MNGMT = USER_MNGMT << 1;

    private static final long READ = READ_NODES | READ_PROPERTIES;
    private static final long MODIFY_PROPERTIES = ADD_PROPERTIES | ALTER_PROPERTIES | REMOVE_PROPERTIES;
    private static final long WRITE = MODIFY_PROPERTIES | ADD_CHILD_NODES | REMOVE_CHILD_NODES | REMOVE_NODE;
    private static final long WRITE2 = WRITE | NODE_TYPE_MNGMT;

    public static final PrivilegeBits EMPTY = new PrivilegeBits(UnmodifiableData.EMPTY);

    public static final Map<String, PrivilegeBits> BUILT_IN = new HashMap<String, PrivilegeBits>();
    static {
        BUILT_IN.put(REP_READ_NODES, getInstance(READ_NODES));
        BUILT_IN.put(REP_READ_PROPERTIES, getInstance(READ_PROPERTIES));
        BUILT_IN.put(REP_ADD_PROPERTIES, getInstance(ADD_PROPERTIES));
        BUILT_IN.put(REP_ALTER_PROPERTIES, getInstance(ALTER_PROPERTIES));
        BUILT_IN.put(REP_REMOVE_PROPERTIES, getInstance(REMOVE_PROPERTIES));
        BUILT_IN.put(JCR_ADD_CHILD_NODES, getInstance(ADD_CHILD_NODES));
        BUILT_IN.put(JCR_REMOVE_CHILD_NODES, getInstance(REMOVE_CHILD_NODES));
        BUILT_IN.put(JCR_REMOVE_NODE, getInstance(REMOVE_NODE));
        BUILT_IN.put(JCR_READ_ACCESS_CONTROL, getInstance(READ_AC));
        BUILT_IN.put(JCR_MODIFY_ACCESS_CONTROL, getInstance(MODIFY_AC));
        BUILT_IN.put(JCR_NODE_TYPE_MANAGEMENT, getInstance(NODE_TYPE_MNGMT));
        BUILT_IN.put(JCR_VERSION_MANAGEMENT, getInstance(VERSION_MNGMT));
        BUILT_IN.put(JCR_LOCK_MANAGEMENT, getInstance(LOCK_MNGMT));
        BUILT_IN.put(JCR_LIFECYCLE_MANAGEMENT, getInstance(LIFECYCLE_MNGMT));
        BUILT_IN.put(JCR_RETENTION_MANAGEMENT, getInstance(RETENTION_MNGMT));
        BUILT_IN.put(JCR_WORKSPACE_MANAGEMENT, getInstance(WORKSPACE_MNGMT));
        BUILT_IN.put(JCR_NODE_TYPE_DEFINITION_MANAGEMENT, getInstance(NODE_TYPE_DEF_MNGMT));
        BUILT_IN.put(JCR_NAMESPACE_MANAGEMENT, getInstance(NAMESPACE_MNGMT));
        BUILT_IN.put(REP_PRIVILEGE_MANAGEMENT, getInstance(PRIVILEGE_MNGMT));
        BUILT_IN.put(REP_USER_MANAGEMENT, getInstance(USER_MNGMT));
        BUILT_IN.put(REP_INDEX_DEFINITION_MANAGEMENT, getInstance(INDEX_DEFINITION_MNGMT));

        BUILT_IN.put(JCR_READ, PrivilegeBits.getInstance(READ));
        BUILT_IN.put(JCR_MODIFY_PROPERTIES, PrivilegeBits.getInstance(MODIFY_PROPERTIES));
        BUILT_IN.put(JCR_WRITE, PrivilegeBits.getInstance(WRITE));
        BUILT_IN.put(REP_WRITE, PrivilegeBits.getInstance(WRITE2));
    }

    public static final PrivilegeBits NEXT_AFTER_BUILT_INS = getInstance(INDEX_DEFINITION_MNGMT).nextBits();

    private final Data d;

    /**
     * Private constructor.
     *
     * @param d The data that backs this instance.
     */
    private PrivilegeBits(Data d) {
        this.d = d;
    }

    /**
     * Creates a mutable instance of privilege bits.
     *
     * @return a new instance of privilege bits.
     */
    public static PrivilegeBits getInstance() {
        return new PrivilegeBits(new ModifiableData());
    }

    /**
     * Creates a mutable instance of privilege bits.
     *
     * @param base The base for this mutable instance.
     * @return a new instance of privilege bits.
     */
    @NotNull
    public static PrivilegeBits getInstance(@NotNull PrivilegeBits... base) {
        PrivilegeBits bts = getInstance();
        for (PrivilegeBits baseBits : base) {
            bts.add(baseBits);
        }
        return bts;
    }

    /**
     * Get or create an instance of privilege bits for a specific property that
     * stores privileges.
     *
     * @param property The property state storing privilege bits information.
     * @return an instance of {@code PrivilegeBits}
     */
    @NotNull
    public static PrivilegeBits getInstance(@Nullable PropertyState property) {
        if (property == null) {
            return EMPTY;
        }

        int size = property.count();
        if (size == 1) {
            return getInstance(property.getValue(Type.LONG, 0));
        } else {
            long[] longs = new long[size];
            for (int i = 0; i < longs.length; i++) {
                longs[i] = property.getValue(Type.LONG, i);
            }
            return getInstance(longs);
        }
    }

    /**
     * Get or create an instance of privilege bits for a privilege definition.
     *
     * @param tree A privilege definition tree or the privileges root.
     * @return an instance of {@code PrivilegeBits}
     */
    @NotNull
    public static PrivilegeBits getInstance(@Nullable Tree tree) {
        if (tree == null) {
            return EMPTY;
        }
        String privName = tree.getName();
        if (BUILT_IN.containsKey(privName)) {
            return BUILT_IN.get(privName);
        } else if (REP_PRIVILEGES.equals(privName)) {
            return getInstance(tree.getProperty(REP_NEXT));
        } else {
            return getInstance(tree.getProperty(REP_BITS));
        }
    }

    /**
     * Internal method to get or create an instance of privilege bits for the
     * specified long value.
     *
     * @param bits A long value.
     * @return an instance of {@code PrivilegeBits}
     */
    @NotNull
    private static PrivilegeBits getInstance(long bits) {
        if (bits == NO_PRIVILEGE) {
            return EMPTY;
        } else {
            checkArgument(bits > NO_PRIVILEGE);
            return new PrivilegeBits(new UnmodifiableData(bits));
        }
    }

    /**
     * Internal method to create a new instance of {@code PrivilegeBits}.
     *
     * @param bits A long array.
     * @return an instance of {@code PrivilegeBits}
     */
    @NotNull
    private static PrivilegeBits getInstance(long[] bits) {
        return new PrivilegeBits(new UnmodifiableData(bits));
    }

    /**
     * Calculate the granted permissions by evaluating the given privileges. Note,
     * that only built-in privileges can be mapped to permissions. Any other
     * privileges will be ignored.
     *
     * @param bits The set of privileges present at given tree.
     * @param parentBits The privileges present on the parent tree. These are
     * required in order to determine permissions that include a modification
     * of the parent tree (add_child_nodes, remove_child_nodes).
     * @param isAllow {@code true} if the privileges are granted; {@code false}
     * otherwise.
     * @return the resulting permissions.
     */
    public static long calculatePermissions(@NotNull PrivilegeBits bits,
                                            @NotNull PrivilegeBits parentBits,
                                            boolean isAllow) {
        long privs = bits.d.longValue();
        long parentPrivs = parentBits.d.longValue();
        long perm = Permissions.NO_PERMISSION;
        if ((privs & READ) == READ) {
            perm |= Permissions.READ;
        } else {
            if ((privs & READ_NODES) == READ_NODES) {
                perm |= Permissions.READ_NODE;
            } else if (((privs & READ_PROPERTIES) == READ_PROPERTIES)) {
                perm |= Permissions.READ_PROPERTY;
            }
        }
        if ((privs & MODIFY_PROPERTIES) == MODIFY_PROPERTIES) {
            perm |= Permissions.SET_PROPERTY;
        } else {
            if ((privs & ADD_PROPERTIES) == ADD_PROPERTIES) {
                perm |= Permissions.ADD_PROPERTY;
            }
            if ((privs & ALTER_PROPERTIES) == ALTER_PROPERTIES) {
                perm |= Permissions.MODIFY_PROPERTY;
            }
            if ((privs & REMOVE_PROPERTIES) == REMOVE_PROPERTIES) {
                perm |= Permissions.REMOVE_PROPERTY;
            }
        }

        // add_node permission is granted through privilege on the parent.
        if ((parentPrivs & ADD_CHILD_NODES) == ADD_CHILD_NODES) {
            perm |= Permissions.ADD_NODE;
        }

        /*
         remove_node is
         allowed: only if remove_child_nodes privilege is present on
                  the parent AND remove_node is present on the node itself
         denied : if either remove_child_nodes is denied on the parent
                  OR remove_node is denied on the node itself.
        */
        if (isAllow) {
            if ((parentPrivs & REMOVE_CHILD_NODES) == REMOVE_CHILD_NODES &&
                    (privs & REMOVE_NODE) == REMOVE_NODE) {
                perm |= Permissions.REMOVE_NODE;
            }
        } else {
            if ((parentPrivs & REMOVE_CHILD_NODES) == REMOVE_CHILD_NODES ||
                    (privs & REMOVE_NODE) == REMOVE_NODE) {
                perm |= Permissions.REMOVE_NODE;
            }
        }

        // modify_child_node_collection permission
        if ((privs & ADD_CHILD_NODES) == ADD_CHILD_NODES &&
                (privs & REMOVE_CHILD_NODES) == REMOVE_CHILD_NODES) {
            perm |= Permissions.MODIFY_CHILD_NODE_COLLECTION;
        }

        // the remaining (special) permissions are simply defined on the node
        if ((privs & READ_AC) == READ_AC) {
            perm |= Permissions.READ_ACCESS_CONTROL;
        }
        if ((privs & MODIFY_AC) == MODIFY_AC) {
            perm |= Permissions.MODIFY_ACCESS_CONTROL;
        }
        if ((privs & LIFECYCLE_MNGMT) == LIFECYCLE_MNGMT) {
            perm |= Permissions.LIFECYCLE_MANAGEMENT;
        }
        if ((privs & LOCK_MNGMT) == LOCK_MNGMT) {
            perm |= Permissions.LOCK_MANAGEMENT;
        }
        if ((privs & NODE_TYPE_MNGMT) == NODE_TYPE_MNGMT) {
            perm |= Permissions.NODE_TYPE_MANAGEMENT;
        }
        if ((privs & RETENTION_MNGMT) == RETENTION_MNGMT) {
            perm |= Permissions.RETENTION_MANAGEMENT;
        }
        if ((privs & VERSION_MNGMT) == VERSION_MNGMT) {
            perm |= Permissions.VERSION_MANAGEMENT;
        }
        if ((privs & WORKSPACE_MNGMT) == WORKSPACE_MNGMT) {
            perm |= Permissions.WORKSPACE_MANAGEMENT;
        }
        if ((privs & NODE_TYPE_DEF_MNGMT) == NODE_TYPE_DEF_MNGMT) {
            perm |= Permissions.NODE_TYPE_DEFINITION_MANAGEMENT;
        }
        if ((privs & NAMESPACE_MNGMT) == NAMESPACE_MNGMT) {
            perm |= Permissions.NAMESPACE_MANAGEMENT;
        }
        if ((privs & PRIVILEGE_MNGMT) == PRIVILEGE_MNGMT) {
            perm |= Permissions.PRIVILEGE_MANAGEMENT;
        }
        if ((privs & USER_MNGMT) == USER_MNGMT) {
            perm |= Permissions.USER_MANAGEMENT;
        }
        if ((privs & INDEX_DEFINITION_MNGMT) == INDEX_DEFINITION_MNGMT) {
            perm |= Permissions.INDEX_DEFINITION_MANAGEMENT;
        }
        return perm;
    }

    /**
     * Returns {@code true} if this privilege bits includes no privileges
     * at all.
     *
     * @return {@code true} if this privilege bits includes no privileges
     *         at all; {@code false} otherwise.
     * @see org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions#NO_PERMISSION
     */
    public boolean isEmpty() {
        return d.isEmpty();
    }

    /**
     * Returns an unmodifiable instance.
     *
     * @return an unmodifiable {@code PrivilegeBits} instance.
     */
    @NotNull
    public PrivilegeBits unmodifiable() {
        if (d instanceof ModifiableData) {
            if (d.isSimple()) {
                return getInstance(d.longValue());
            } else {
                long[] bits = d.longValues();
                long[] copy = new long[bits.length];
                System.arraycopy(bits, 0, copy, 0, bits.length);
                return getInstance(copy);
            }
        } else {
            return this;
        }
    }

    @NotNull
    public PrivilegeBits modifiable() {
        if (d instanceof ModifiableData) {
            return this;
        } else {
            return getInstance(this);
        }
    }

    /**
     * Returns {@code true} if all privileges defined by the specified
     * {@code otherBits} are present in this instance.
     *
     * @param otherBits
     * @return {@code true} if all privileges defined by the specified
     *         {@code otherBits} are included in this instance; {@code false}
     *         otherwise.
     */
    public boolean includes(@NotNull PrivilegeBits otherBits) {
        return d.includes(otherBits.d);
    }

    /**
     * Adds the other privilege bits to this instance.
     *
     * @param other The other privilege bits to be added.
     * @return The updated instance.
     * @throws UnsupportedOperationException if this instance is immutable.
     */
    @NotNull
    public PrivilegeBits add(@NotNull PrivilegeBits other) {
        if (d instanceof ModifiableData) {
            ((ModifiableData) d).add(other.d);
            return this;
        } else {
            throw unsupported();
        }
    }

    /**
     * Subtracts the other PrivilegeBits from the this.<br>
     * If the specified bits do not intersect with this, it isn't modified.<br>
     * If {@code this} is included in {@code other} {@link #EMPTY empty}
     * privilege bits is returned.
     *
     * @param other The other privilege bits to be subtracted from this instance.
     * @return The updated instance.
     * @throws UnsupportedOperationException if this instance is immutable.
     */
    @NotNull
    public PrivilegeBits diff(@NotNull PrivilegeBits other) {
        if (d instanceof ModifiableData) {
            ((ModifiableData) d).diff(other.d);
            return this;
        } else {
            throw unsupported();
        }
    }

    /**
     * Subtracts the {@code b} from {@code a} and adds the result (diff)
     * to this instance.
     *
     * @param a An instance of privilege bits.
     * @param b An instance of privilege bits.
     * @return The updated instance.
     * @throws UnsupportedOperationException if this instance is immutable.
     */
    @NotNull
    public PrivilegeBits addDifference(@NotNull PrivilegeBits a, @NotNull PrivilegeBits b) {
        if (d instanceof ModifiableData) {
            ((ModifiableData) d).addDifference(a.d, b.d);
            return this;
        } else {
            throw unsupported();
        }
    }

    /**
     * Retains the elements in this {@code PrivilegeBits} that are contained in
     * the specified other {@code PrivilegeBits}.
     *
     * @param other Other privilege bits.
     * @return This modifiable instance of privilege bits modified such it contains
     * only privileges that were also contained in the {@code other} instance.
     */
    @NotNull
    public PrivilegeBits retain(@NotNull PrivilegeBits other) {
        if (d instanceof ModifiableData) {
            ((ModifiableData) d).retain(other.d);
            return this;
        }  else {
            throw unsupported();
        }
    }

    @NotNull
    public PropertyState asPropertyState(String name) {
        return PropertyStates.createProperty(name, Longs.asList(d.longValues()), Type.LONGS);
    }

    /**
     * Method to calculate the next privilege bits associated with this instance.
     *
     * @return an new instance of {@code PrivilegeBits}
     */
    @NotNull
    public PrivilegeBits nextBits() {
        if (this == EMPTY) {
            return EMPTY;
        } else {
            return new PrivilegeBits(d.next());
        }
    }

    /**
     * Write this instance as property to the specified tree.
     *
     * @param tree The target tree.
     */
    public void writeTo(@NotNull Tree tree) {
        String name = (REP_PRIVILEGES.equals(tree.getName())) ? REP_NEXT : REP_BITS;
        tree.setProperty(asPropertyState(name));
    }

    private static UnsupportedOperationException unsupported() {
        return new UnsupportedOperationException("immutable privilege bits");
    }

    //-------------------------------------------------------------< Object >---
    @Override
    public int hashCode() {
        return d.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (o instanceof PrivilegeBits) {
            return d.equals(((PrivilegeBits) o).d);
        } else {
            return false;
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("PrivilegeBits: ");
        if (d.isSimple()) {
            sb.append(d.longValue());
        } else {
            sb.append(Arrays.toString(d.longValues()));
        }
        return sb.toString();
    }

    //------------------------------------------------------< inner classes >---

    /**
     * Base class for the internal privilege bits representation and handling.
     */
    private abstract static class Data {

        abstract boolean isEmpty();

        abstract long longValue();

        abstract long[] longValues();

        abstract boolean isSimple();

        abstract Data next();

        abstract boolean includes(Data other);

        /**
         * Checks if all {@code otherBits} is already included in {@code bits}.
         * <p>
         * Truth table:
         * <pre>
         * | b\o | 0 | 1 |
         * |  0  | 1 | 0 |
         * |  1 |  1 | 1 |
         * </pre>
         * @param bits the super set of bits
         * @param otherBits the bits to check against
         * @return {@code true} if all other bits are included in bits.
         */
        static boolean includes(long bits, long otherBits) {
            return (bits | ~otherBits) == -1;
        }

        /**
         * Checks if all {@code otherBits} is already included in {@code bits}.
         * <p>
         * Truth table:
         * <pre>
         * | b\o | 0 | 1 |
         * |  0  | 1 | 0 |
         * |  1 |  1 | 1 |
         * </pre>
         * @param bits the super set of bits
         * @param otherBits the bits to check against
         * @return {@code true} if all other bits are included in bits.
         */
        static boolean includes(long[] bits, long[] otherBits) {
            if (otherBits.length <= bits.length) {
                // test for each long if is included
                for (int i = 0; i < otherBits.length; i++) {
                    if ((bits[i] | ~otherBits[i]) != -1) {
                        return false;
                    }
                }
                return true;
            } else {
                // otherbits array is longer > cannot be included in bits
                return false;
            }
        }
    }

    /**
     * Immutable Data object
     */
    private static final class UnmodifiableData extends Data {

        private static final long MAX = Long.MAX_VALUE / 2;
        private static final UnmodifiableData EMPTY = new UnmodifiableData(NO_PRIVILEGE);

        private final long bits;
        private final long[] bitsArr;
        private final boolean isSimple;

        private UnmodifiableData(long bits) {
            this.bits = bits;
            bitsArr = new long[]{bits};
            isSimple = true;
        }

        private UnmodifiableData(long[] bitsArr) {
            bits = NO_PRIVILEGE;
            this.bitsArr = bitsArr;
            isSimple = false;
        }

        @Override
        boolean isEmpty() {
            return this == EMPTY;
        }

        @Override
        long longValue() {
            return bits;
        }

        @Override
        long[] longValues() {
            return bitsArr;
        }

        @Override
        boolean isSimple() {
            return isSimple;
        }

        @Override
        Data next() {
            if (this == EMPTY) {
                return EMPTY;
            } else if (isSimple) {
                if (bits < MAX) {
                    long b = bits << 1;
                    return new UnmodifiableData(b);
                } else {
                    return new UnmodifiableData(new long[]{bits}).next();
                }
            } else {
                long[] bts;
                long last = bitsArr[bitsArr.length - 1];
                if (last < MAX) {
                    bts = new long[bitsArr.length];
                    System.arraycopy(bitsArr, 0, bts, 0, bitsArr.length);
                    bts[bts.length - 1] = last << 1;
                } else {
                    bts = new long[bitsArr.length + 1];
                    bts[bts.length - 1] = 1;
                }
                return new UnmodifiableData(bts);
            }
        }

        @Override
        boolean includes(Data other) {
            if (isSimple) {
                return (other.isSimple()) && includes(bits, other.longValue());
            } else {
                return includes(bitsArr, other.longValues());
            }
        }

        //---------------------------------------------------------< Object >---
        @Override
        public int hashCode() {
            return (isSimple) ? Long.valueOf(bits).hashCode() : Arrays.hashCode(bitsArr);
        }

        @Override
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            } else if (o instanceof UnmodifiableData) {
                UnmodifiableData d = (UnmodifiableData) o;
                if (isSimple != d.isSimple) {
                    return false;
                }
                if (isSimple) {
                    return bits == d.bits;
                } else {
                    return Arrays.equals(bitsArr, d.bitsArr);
                }
            } else {
                return false;
            }
        }
    }

    /**
     * Mutable implementation of the Data base class.
     */
    private static final class ModifiableData extends Data {

        private long[] bits;

        private ModifiableData() {
            bits = new long[]{NO_PRIVILEGE};
        }

        @Override
        boolean isEmpty() {
            return bits.length == 1 && bits[0] == NO_PRIVILEGE;
        }

        @Override
        long longValue() {
            return (bits.length == 1) ? bits[0] : NO_PRIVILEGE;
        }

        @Override
        long[] longValues() {
            return bits;
        }

        @Override
        boolean isSimple() {
            return bits.length == 1;
        }

        @Override
        Data next() {
            throw new UnsupportedOperationException("Not implemented.");
        }

        @Override
        boolean includes(Data other) {
            if (bits.length == 1) {
                return other.isSimple() && includes(bits[0], other.longValue());
            } else {
                return includes(bits, other.longValues());
            }
        }

        /**
         * Add the other Data to this instance.
         *
         * @param other
         */
        private void add(Data other) {
            if (other != this) {
                if (bits.length == 1 && other.isSimple()) {
                    bits[0] |= other.longValue();
                } else {
                    or(other.longValues());
                }
            }
        }

        /**
         * Subtract the other Data from this instance.
         *
         * @param other
         */
        private void diff(Data other) {
            if (bits.length == 1 && other.isSimple()) {
                bits[0] = bits[0] & ~other.longValue();
            } else {
                bits = diff(bits, other.longValues());
            }
        }

        /**
         * Add the diff between the specified Data a and b.
         *
         * @param a
         * @param b
         */
        private void addDifference(Data a, Data b) {
            if (a.isSimple() && b.isSimple()) {
                bits[0] |= a.longValue() & ~b.longValue();
            } else {
                long[] diff = diff(a.longValues(), b.longValues());
                or(diff);
            }
        }

        private void or(long[] b) {
            if (b.length > bits.length) {
                // enlarge the array
                long[] res = new long[b.length];
                System.arraycopy(bits, 0, res, 0, bits.length);
                bits = res;
            }
            for (int i = 0; i < b.length; i++) {
                bits[i] |= b[i];
            }
        }

        private void retain(Data other) {
            if (isSimple()) {
                bits[0] &= other.longValue();
            } else {
                long[] lvs = longValues();
                long[] bLvs = other.longValues();

                long[] res = (lvs.length <= bLvs.length) ? new long[lvs.length] : new long[bLvs.length];
                int compactSize = -1;
                for (int i = 0; i < res.length; i++) {
                    res[i] = (lvs[i] & bLvs[i]);
                    if (res[i] == 0) {
                        if (compactSize == -1) {
                            compactSize = i+1;
                        }
                    } else {
                        compactSize = -1;
                    }
                }
                if (compactSize != -1 && res.length > compactSize) {
                    bits = Arrays.copyOfRange(res, 0, compactSize);
                } else {
                    bits = res;
                }
            }
        }

        private static long[] diff(long[] a, long[] b) {
            int index = -1;
            long[] res = new long[((a.length > b.length) ? a.length : b.length)];
            for (int i = 0; i < res.length; i++) {
                if (i < a.length && i < b.length) {
                    res[i] = a[i] & ~b[i];
                } else {
                    res[i] = (i < a.length) ? a[i] : 0;
                }
                // remember start of trailing 0 array entries
                if (res[i] != 0) {
                    index = -1;
                } else if (index == -1) {
                    index = i;
                }
            }
            switch (index) {
                case -1:
                    // no need to remove trailing 0-long from the array
                    return res;
                case 0:
                    // array consisting of one or multiple 0
                    return new long[]{NO_PRIVILEGE};
                default:
                    // remove trailing 0-long entries from the array
                    long[] r2 = new long[index];
                    System.arraycopy(res, 0, r2, 0, index);
                    return r2;
            }
        }
    }
}
