/*
 * 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.netbeans.lib.v8debug.vars;

import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import org.netbeans.lib.v8debug.PropertyLong;

/**
 *
 * @author Martin Entlicher
 */
public class V8Object extends V8Value {
    
    private final String className;
    private final PropertyLong constructorFunctionHandle;
    private final PropertyLong protoObjectHandle;
    private final PropertyLong prototypeObjectHandle;
    private final Map<String, Property> properties;
    private final Array array;
    
    public V8Object(long handle, V8Value.Type type, String className,
                    PropertyLong constructorFunctionHandle,
                    PropertyLong protoObjectHandle, PropertyLong prototypeObjectHandle,
                    Map<String, Property> properties, Array array, String text) {
        super(handle, type, text);
        this.className = className;
        this.constructorFunctionHandle = constructorFunctionHandle;
        this.protoObjectHandle = protoObjectHandle;
        this.prototypeObjectHandle = prototypeObjectHandle;
        this.properties = properties;
        this.array = array;
    }
    
    protected V8Object(long handle, V8Value.Type type, String className,
                       PropertyLong constructorFunctionHandle,
                       PropertyLong protoObjectHandle, PropertyLong prototypeObjectHandle,
                       Map<String, Property> properties, String text) {
        this(handle, type, className, constructorFunctionHandle,
             protoObjectHandle, prototypeObjectHandle, properties, null, text);
    }
    
    public String getClassName() {
        return className;
    }

    public PropertyLong getConstructorFunctionHandle() {
        return constructorFunctionHandle;
    }

    public PropertyLong getProtoObjectHandle() {
        return protoObjectHandle;
    }

    public PropertyLong getPrototypeObjectHandle() {
        return prototypeObjectHandle;
    }

    public Map<String, Property> getProperties() {
        return properties;
    }
    
    public Array getArray() {
        return array;
    }
    
    public static final class Property {
        
        public static enum Type {
            Normal,
            Field,
            Constant,
            Callbacks,
            Handler,
            Interceptor,
            Transition,
            Nonexistent
        }
        
        public static final int ATTR_NONE = 0;
        public static final int ATTR_READ_ONLY = 1;
        public static final int ATTR_DONT_ENUM = 2;
        public static final int ATTR_DONT_DELETE = 4;
        public static final int ATTR_SEALED = ATTR_DONT_DELETE;
        public static final int ATTR_FROZEN = ATTR_SEALED | ATTR_READ_ONLY;
        public static final int ATTR_STRING = 8;
        public static final int ATTR_SYMBOLIC = 16;
        public static final int ATTR_PRIVATE_SYMBOL = 32;
        public static final int ATTR_DONT_SHOW = ATTR_DONT_ENUM | ATTR_SYMBOLIC | ATTR_PRIVATE_SYMBOL;
        public static final int ATTR_ABSENT = 64;
        
        private final String name;
        private final Type type;
        private final int attributes;
        private final long reference;
        
        public Property(String name, Type type, int attributes, long reference) {
            this.name = name;
            this.type = type;
            this.attributes = attributes;
            this.reference = reference;
        }

        public String getName() {
            return name;
        }

        public Type getType() {
            return type;
        }

        public int getAttributes() {
            return attributes;
        }

        public long getReference() {
            return reference;
        }
        
    }
    
    public static interface Array {
        
        long getReferenceAt(long index) throws NoSuchElementException;
        
        IndexIterator getIndexIterator();
        
        boolean isContiguous();
        
        long[] getContiguousReferences() throws UnsupportedOperationException;
        
        long getLength();
    }
    
    public static interface IndexIterator {
        
        boolean hasNextIndex();
        
        long nextIndex() throws NoSuchElementException;
    }
    
    public static final class DefaultArray implements Array {
        
        private long[] references;
        private long[] indexes;
        private int length;
        
        public DefaultArray(long[] references) {
            this.references = references;
            this.indexes = null;
            this.length = references.length;
        }
        
        public DefaultArray() {
            this.references = new long[0];
            this.indexes = null;
            this.length = 0;
        }
        
        public void putReferenceAt(long index, long reference) {
            if (indexes == null) {
                // we're contiguous so far
                if (index < length) {
                    references[(int) index] = reference;
                } else if (index == length) {
                    if (references.length <= index) {
                        int newLength = getNewLength();
                        references = Arrays.copyOf(references, newLength);
                    }
                    references[length++] = reference;
                } else {
                    // switch to non-contiguous
                    int newLength = references.length;
                    if (!(newLength > length)) {
                        newLength = getNewLength();
                        references = Arrays.copyOf(references, newLength);
                    }
                    indexes = new long[newLength];
                    for (int i = 0; i < length; i++) {
                        indexes[i] = i;
                    }
                    indexes[length] = index;
                    references[length] = reference;
                    length++;
                }
            } else {
                if (references.length <= length) {
                    int newLength = getNewLength();
                    references = Arrays.copyOf(references, newLength);
                    indexes = Arrays.copyOf(indexes, newLength);
                }
                indexes[length] = index;
                references[length] = reference;
                length++;
            }
        }
        
        private int getNewLength() {
            int newLength = length + (length >> 1);
            if (newLength < 10) {
                newLength = 10;
            }
            if (!(newLength > length)) {
                // overflow
                newLength = Integer.MAX_VALUE - 8;
                if (!(newLength > length)) {
                    if (length == Integer.MAX_VALUE) {
                        throw new OutOfMemoryError("Unable to allocate an array longer than "+Integer.MAX_VALUE+" bytes.");
                    }
                    newLength = Integer.MAX_VALUE;
                }
            }
            return newLength;
        }
        
        @Override
        public long getReferenceAt(long index) throws NoSuchElementException {
            if (indexes == null) {
                if (index >= length) {
                    throw new NoSuchElementException("No reference at "+index+", array length is "+length);
                }
                return references[(int) index];
            } else {
                int pos = getPositionOf(index);
                if (pos < 0) {
                    throw new NoSuchElementException("No reference at "+index);
                }
                return references[pos];
            }
        }
        
        private int getPositionOf(long index) {
            int p1 = 0;
            int p2 = length - 1;
            while (p1 <= p2) {
                int p = p1 + (p2 - p1)/2;
                long pi = indexes[p];
                if (pi == index) {
                    return p;
                }
                if (p1 == p2) {
                    return -1;
                }
                if (pi < index) {
                    if (p1 == p) {
                        p1++;
                    } else {
                        p1 = p;
                    }
                } else {
                    p2 = p;
                }
            }
            return -1;
        }

        @Override
        public IndexIterator getIndexIterator() {
            return new DefaultIndexIterator();
        }

        @Override
        public boolean isContiguous() {
            return indexes == null;
        }

        @Override
        public long[] getContiguousReferences() throws UnsupportedOperationException {
            if (indexes == null) {
                if (references.length > length) {
                    // trim
                    references = Arrays.copyOf(references, length);
                }
                return references;
            } else {
                throw new UnsupportedOperationException("The array is not contiguous.");
            }
        }

        @Override
        public long getLength() {
            if (indexes == null) {
                return length;
            } else {
                if (length == 0) {
                    return 0;
                } else {
                    long maxIndex = indexes[length-1];
                    return maxIndex + 1;
                }
            }
        }
        
        private final class DefaultIndexIterator implements IndexIterator {
            
            private int pos = 0;

            @Override
            public boolean hasNextIndex() {
                return pos < length;
            }

            @Override
            public long nextIndex() throws NoSuchElementException {
                if (pos >= length) {
                    throw new NoSuchElementException("Length = "+length);
                }
                if (indexes == null) {
                    return pos++;
                } else {
                    return indexes[pos++];
                }
            }
        
        }
    }
    
}
