/*******************************************************************************
 * Copyright (c) 2008, 2021 SAP AG, Netflix, IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    SAP AG - initial API and implementation
 *    Netflix (Jason Koch) - refactors for increased performance and concurrency
 *    IBM Corporation (Andrew Johnson) - compressed dumps
 *******************************************************************************/
package org.eclipse.mat.hprof;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.hprof.AbstractParser.Constants.Record;
import org.eclipse.mat.hprof.describer.Version;
import org.eclipse.mat.hprof.ui.HprofPreferences;
import org.eclipse.mat.parser.index.IIndexReader.IOne2LongIndex;
import org.eclipse.mat.parser.io.BufferedRandomAccessInputStream;
import org.eclipse.mat.parser.model.AbstractObjectImpl;
import org.eclipse.mat.parser.model.ClassImpl;
import org.eclipse.mat.parser.model.ClassLoaderImpl;
import org.eclipse.mat.parser.model.InstanceImpl;
import org.eclipse.mat.parser.model.ObjectArrayImpl;
import org.eclipse.mat.parser.model.PrimitiveArrayImpl;
import org.eclipse.mat.snapshot.ISnapshot;
import org.eclipse.mat.snapshot.model.Field;
import org.eclipse.mat.snapshot.model.FieldDescriptor;
import org.eclipse.mat.snapshot.model.IArray;
import org.eclipse.mat.snapshot.model.IClass;
import org.eclipse.mat.snapshot.model.IObject;
import org.eclipse.mat.snapshot.model.IPrimitiveArray;
import org.eclipse.mat.snapshot.model.ObjectReference;
import org.eclipse.mat.util.MessageUtil;

public class HprofRandomAccessParser extends AbstractParser
{
    public static final int LAZY_LOADING_LIMIT = 256;
    private final IPositionInputStream in;

    public HprofRandomAccessParser(File file, Version version, int identifierSize, long len,
                    HprofPreferences.HprofStrictness strictnessPreference) throws IOException
    {
        super(strictnessPreference);
        RandomAccessFile raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$
        boolean gzip = CompressedRandomAccessFile.isGZIP(raf);
        if (gzip)
        {
            ChunkedGZIPRandomAccessFile cgraf = ChunkedGZIPRandomAccessFile.get(raf, file);
            raf.close();

            if (cgraf != null)
            {
                raf = cgraf;
            }
            else
            {
                long requested = len / 10;
                long maxFree = CompressedRandomAccessFile.checkMemSpace(requested);
                // If we are very memory constrained use a file cache
                if (requested > maxFree && FileCacheCompressedRandomAccessFile.isDiskSpace(file, len))
                    raf = new FileCacheCompressedRandomAccessFile(file);
                else
                    raf = new CompressedRandomAccessFile(file, true, len);
            }
        }
        this.in = new DefaultPositionInputStream(new BufferedRandomAccessInputStream(raf, 512));
        this.version = version;
        this.idSize = identifierSize;
    }

    public synchronized void close() throws IOException
    {
        in.close();
    }

    public synchronized IObject read(int objectId, long position, ISnapshot dump, IOne2LongIndex o2hprof) throws IOException, SnapshotException
    {
        in.seek(position);
        int segmentType = in.readUnsignedByte();
        if (objectId == -1)
        {
            segmentType = skipRecords(segmentType);
        }
        switch (segmentType)
        {
            case Constants.DumpSegment.INSTANCE_DUMP:
                return readInstanceDump(objectId, dump);
            case Constants.DumpSegment.OBJECT_ARRAY_DUMP:
                return readObjectArrayDump(objectId, dump);
            case Constants.DumpSegment.PRIMITIVE_ARRAY_DUMP:
                return readPrimitiveArrayDump(objectId, dump);
            default:
                throw new IOException(MessageUtil.format(Messages.HprofRandomAccessParser_Error_IllegalDumpSegment,
                                segmentType, Long.toHexString(position)));
        }

    }

    public List<IClass> resolveClassHierarchy(ISnapshot snapshot, IClass clazz) throws SnapshotException
    {
        List<IClass> answer = new ArrayList<IClass>();
        answer.add(clazz);
        while (clazz.hasSuperClass())
        {
            clazz = (IClass) snapshot.getObject(clazz.getSuperClassId());
            if (clazz == null)
                return null;
            answer.add(clazz);
        }

        return answer;
    }

    /**
     * A reference to an object via its address
     * which can handle the address not being in the index.
     */
    static class ObjectAddressReference extends ObjectReference
    {
        private static final long serialVersionUID = 1L;
        transient IOne2LongIndex o2hprof;
        transient ISnapshot snapshot;
        transient HprofRandomAccessParser parser;
        /**
         * Construct an {@link ObjectAddressReference} which can be used to retrieve an
         * object by address even if it has not been indexed.
         * Used as a proxy by {@link ObjectReference} which can change the {@link ObjectReference#address}
         * private field.
         * @param snapshot the snapshot
         * @param parser the HPROF parser used to build the IObject if required
         * @param o2hprof the index from object ID to HPROF file position
         * @param address the address of the object
         */
        public ObjectAddressReference(ISnapshot snapshot, HprofRandomAccessParser parser, IOne2LongIndex o2hprof, long address)
        {
            super(snapshot, address);
            this.snapshot = snapshot;
            this.o2hprof = o2hprof;
            this.parser = parser;
        }
        @Override
        public int getObjectId() throws SnapshotException
        {
            try
            {
                int id = super.getObjectId();
                return id;
            }
            catch (SnapshotException e)
            {
                return -1;
            }
        }
        /**
         * Actually construct an IObject.
         * First try constructing by object ID.
         * If that fails then construct by address.
         * Find the indexed objects before and after this.
         * Parse the HPROF file between these two points looking for an
         * object of the correct address.
         */
        @Override
        public IObject getObject() throws SnapshotException
        {
            SnapshotException e1 = null;
            try
            {
                int id = super.getObjectId();
                if (id >= 0)
                {
                    IObject o = super.getObject();
                    return o;
                }
            }
            catch (SnapshotException e)
            {
                e1 = e;
            }
            // Find the object IDs before and after this object
            int low = 0;
            int high = o2hprof.size() - 1;
            for (;low + 1 < high;)
            {
                int mid = (low + high) >>> 1;
                long midAddr = snapshot.mapIdToAddress(mid);
                if (getObjectAddress() < midAddr)
                {
                    high = mid;
                }
                else if (getObjectAddress() > midAddr)
                {
                    low = mid;
                }
                else
                {
                    low = mid;
                    high = mid;
                }
            }
            // Some objects don't have a position (classes?), so find valid file positions
            long pos = 0;
            while ((pos = o2hprof.get(low)) == 0 && low > 0)
                --low;
            if (pos == 0)
            {
                // There might be discarded objects before the first
                Long lpos = (Long)snapshot.getSnapshotInfo().getProperty(HprofHeapObjectReader.HPROF_HEAP_START);
                if (lpos != null)
                    pos = lpos;
                else while ((pos = o2hprof.get(low)) == 0 && low < o2hprof.size() - 1)
                    ++low;
            }
            long posHigh = pos;
            while (high >= 0 && (posHigh = o2hprof.get(high)) == 0 && high < o2hprof.size() - 1)
                ++high;
            if (posHigh == 0)
            {
                // There might be discarded objects after the last
                Long olen = (Long)snapshot.getSnapshotInfo().getProperty(HprofHeapObjectReader.HPROF_LENGTH_PROPERTY);
                posHigh = (olen != null) ? olen : Long.MAX_VALUE;
            }
            // Reparse the HPROF file looking for an object of the right address
            try
            {
                do
                {
                    IObject o;
                    synchronized (parser)
                    {
                        // Need final position without interference
                        o = parser.read(-1, pos, snapshot, o2hprof);
                        pos = parser.in.position();
                    }
                    if (o.getObjectAddress() == getObjectAddress())
                    {
                        // Class was discarded from the snapshot
                        if (o.getClazz() == null)
                            throw new IOException();
                        ((AbstractObjectImpl)o).setSnapshot(snapshot);
                        return o;
                    }
                    // Gone past the object address we want
                    if (o.getObjectAddress() > getObjectAddress())
                        break;
                }
                while (pos < posHigh);
            }
            catch (IOException e2)
            {
                if (e2 instanceof EOFException)
                    throw e1;
                throw new SnapshotException(e2);
            }
            // Not found, so throw the original exception
            throw e1;
        }
    }

    private IObject readInstanceDump(int objectId, ISnapshot dump) throws IOException, SnapshotException
    {
        long address = in.readID(idSize);
        IClass oclazz;
        if (objectId >= 0)
        {
            // Skip serial number, class ID, length
            if (in.skipBytes(8 + idSize) != 8 + idSize)
                throw new IOException();
            oclazz = dump.getClassOf(objectId);
        }
        else
        {
            // skip serial number
            if (in.skipBytes(4) != 4)
                throw new IOException();
            // class ID
            long classAddr = in.readID(idSize);
            // length
            long len = in.readUnsignedInt();
            try
            {
                int classID = dump.mapAddressToId(classAddr);
                IObject io = dump.getObject(classID);
                if (io instanceof IClass)
                    oclazz = (IClass)io;
                else
                    throw new IOException();
            }
            catch (SnapshotException e)
            {
                // move to end of object
                if (in.skipBytes(len) != len)
                    throw new IOException();
                // Invalid object, but might be good enough for skipping over
                return new InstanceImpl(objectId, address, null, null);
            }
        }

        // check if we need to defer reading the class
        List<IClass> hierarchy = resolveClassHierarchy(dump, oclazz);
        if (hierarchy == null)
        {
            throw new IOException(Messages.HprofRandomAccessParser_Error_DumpIncomplete);
        }
        else
        {
            List<Field> instanceFields = new ArrayList<Field>();
            for (IClass clazz : hierarchy)
            {
                List<FieldDescriptor> fields = clazz.getFieldDescriptors();
                for (int ii = 0; ii < fields.size(); ii++)
                {
                    FieldDescriptor field = fields.get(ii);
                    int type = field.getType();
                    Object value = readValue(in, dump, type);
                    instanceFields.add(new Field(field.getName(), field.getType(), value));
                }
            }

            ClassImpl classImpl = (ClassImpl) hierarchy.get(0);

            if (dump.isClassLoader(objectId))
                return new ClassLoaderImpl(objectId, address, classImpl, instanceFields);
            else
                return new InstanceImpl(objectId, address, classImpl, instanceFields);
        }
    }

    private IArray readObjectArrayDump(int objectId, ISnapshot dump) throws IOException, SnapshotException
    {
        long id = in.readID(idSize);

        in.skipBytes(4);
        int size = in.readInt();
        long len = (long)size * idSize;

        long arrayClassObjectID = in.readID(idSize);

        int typeId;
        if (objectId == -1)
        {
            try
            {
                typeId = dump.mapAddressToId(arrayClassObjectID);
            }
            catch (SnapshotException e)
            {
                ObjectArrayImpl array = new ObjectArrayImpl(objectId, id, null, size);
                // Move to end of object
                if (in.skipBytes(len) != len)
                    throw new IOException();
                return array;
            }
        }
        else
        {
            typeId = dump.mapAddressToId(arrayClassObjectID);
        }
        IClass arrayType = (IClass) dump.getObject(typeId);
        if (arrayType == null)
            throw new RuntimeException(Messages.HprofRandomAccessParser_Error_MissingFakeClass);

        Object content = null;
        if (len < LAZY_LOADING_LIMIT)
        {
            long[] data = new long[size];
            for (int ii = 0; ii < data.length; ii++)
                data[ii] = in.readID(idSize);
            content = data;
        }
        else
        {
            content = new ArrayDescription.Offline(false, in.position(), 0, size);
            if (objectId == -1)
            {
                // Move to end of object
                if (in.skipBytes(len) != len)
                    throw new IOException();
            }
        }

        ObjectArrayImpl array = new ObjectArrayImpl(objectId, id, (ClassImpl) arrayType, size);
        array.setInfo(content);
        return array;
    }

    private IArray readPrimitiveArrayDump(int objectId, ISnapshot dump) throws IOException, SnapshotException
    {
        long id = in.readID(idSize);

        in.skipBytes(4);
        int arraySize = in.readInt();

        long elementType = in.readByte();
        if ((elementType < IPrimitiveArray.Type.BOOLEAN) || (elementType > IPrimitiveArray.Type.LONG))
            throw new IOException(Messages.Pass1Parser_Error_IllegalType);

        int elementSize = IPrimitiveArray.ELEMENT_SIZE[(int) elementType];
        long len = elementSize * (long)arraySize;

        Object content = null;
        if (len < LAZY_LOADING_LIMIT)
        {
            byte[] data = new byte[(int)len];
            in.readFully(data);
            content = elementType == IObject.Type.BYTE ? data : new ArrayDescription.Raw(data);
        }
        else
        {
            content = new ArrayDescription.Offline(true, in.position(), elementSize, arraySize);
            if (objectId == -1)
            {
                // Move to end of object
                if (in.skipBytes(len) != len)
                    throw new IOException();
            }
        }

        // lookup class by name
        IClass clazz = null;
        String name = IPrimitiveArray.TYPE[(int) elementType];
        Collection<IClass> classes = dump.getClassesByName(name, false);
        if (classes == null || classes.isEmpty())
        {
            if (objectId == -1)
            {
                // Return a dummy array which can be ignored
                PrimitiveArrayImpl array = new PrimitiveArrayImpl(objectId, id, (ClassImpl) clazz, arraySize, (int) elementType);
                return array;
            }
            throw new IOException(MessageUtil.format(Messages.HprofRandomAccessParser_Error_MissingClass, name));
        }
        else if (classes.size() > 1)
            throw new IOException(MessageUtil.format(Messages.HprofRandomAccessParser_Error_DuplicateClass, name));
        else
            clazz = classes.iterator().next();

        PrimitiveArrayImpl array = new PrimitiveArrayImpl(objectId, id, (ClassImpl) clazz, arraySize, (int) elementType);
        array.setInfo(content);

        return array;
    }

    public synchronized long[] readObjectArray(ArrayDescription.Offline descriptor, int offset, int length)
                    throws IOException
    {
        int elementSize = this.idSize;

        in.seek(descriptor.getPosition() + ((long)offset * elementSize));
        long[] data = new long[length];
        for (int ii = 0; ii < data.length; ii++)
            data[ii] = in.readID(idSize);
        return data;
    }

    public synchronized byte[] readPrimitiveArray(ArrayDescription.Offline descriptor, int offset, int length)
                    throws IOException
    {
        int elementSize = descriptor.getElementSize();

        in.seek(descriptor.getPosition() + ((long)offset * elementSize));

        byte[] data = new byte[length * elementSize];
        in.readFully(data);
        return data;
    }

    private int skipRecords(int segmentType) throws IOException
    {
        boolean again = true;
        do
        {
            int skip = -1;
            switch (segmentType)
            {
                case Record.HEAP_DUMP_SEGMENT:
                    skip = 8;
                    break;
                case Constants.DumpSegment.ROOT_UNKNOWN:
                case Constants.DumpSegment.ROOT_STICKY_CLASS:
                case Constants.DumpSegment.ROOT_MONITOR_USED:
                    skip = idSize;
                    break;
                case Constants.DumpSegment.ROOT_JNI_GLOBAL:
                    skip = idSize * 2;
                    break;
                case Constants.DumpSegment.ROOT_JNI_LOCAL:
                case Constants.DumpSegment.ROOT_JAVA_FRAME:
                case Constants.DumpSegment.ROOT_THREAD_OBJECT:
                    skip = idSize + 8;
                    break;
                case Constants.DumpSegment.ROOT_NATIVE_STACK:
                case Constants.DumpSegment.ROOT_THREAD_BLOCK:
                    skip = idSize + 4;
                    break;
                case Constants.DumpSegment.CLASS_DUMP:
                    skipClassDump();
                    // Already skipped enough, so just reread
                    skip = 0;
                    break;
                default:
                    again = false;
                    break;
            }
            if (skip >= 0)
            {
                // Skip over new segment header etc.
                in.skipBytes(skip);
                segmentType = in.readUnsignedByte();
            }
        }
        while (again);
        return segmentType;
    }

    private void skipClassDump() throws IOException
    {
        in.skipBytes(7 * idSize + 8);

        int constantPoolSize = in.readUnsignedShort();
        for (int ii = 0; ii < constantPoolSize; ii++)
        {
            in.skipBytes(2);
            skipValue(in);
        }

        int numStaticFields = in.readUnsignedShort();
        for (int i = 0; i < numStaticFields; i++)
        {
            in.skipBytes(idSize);
            skipValue(in);
        }

        int numInstanceFields = in.readUnsignedShort();
        in.skipBytes((idSize + 1) * numInstanceFields);
    }
}
