/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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 com.android.ide.eclipse.gltrace;

import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage;
import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
import com.android.ide.eclipse.gltrace.format.GLAPISpec;
import com.android.ide.eclipse.gltrace.format.GLMessageFormatter;
import com.android.ide.eclipse.gltrace.model.GLCall;
import com.android.ide.eclipse.gltrace.model.GLFrame;
import com.android.ide.eclipse.gltrace.model.GLTrace;
import com.android.ide.eclipse.gltrace.state.transforms.StateTransformFactory;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class TraceFileParserTask implements IRunnableWithProgress {
    private static final TraceFileReader sReader = new TraceFileReader();

    private static final GLMessageFormatter sGLMessageFormatter =
            new GLMessageFormatter(GLAPISpec.getSpecs());

    private String mTraceFilePath;
    private RandomAccessFile mFile;

    private List<GLCall> mGLCalls;
    private Set<Integer> mGLContextIds;

    private GLTrace mTrace;

    /**
     * Construct a GL Trace file parser.
     * @param path path to trace file
     */
    public TraceFileParserTask(String path) {
        try {
            mFile = new RandomAccessFile(path, "r"); //$NON-NLS-1$
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException(e);
        }

        mTraceFilePath = path;
        mGLCalls = new ArrayList<GLCall>();
        mGLContextIds = new TreeSet<Integer>();
    }

    private void addMessage(int index, long traceFileOffset, GLMessage msg, long startTime) {
        String formattedMsg;
        try {
            formattedMsg = sGLMessageFormatter.formatGLMessage(msg);
        } catch (Exception e) {
            formattedMsg = String.format("%s()", msg.getFunction().toString()); //$NON-NLS-1$
        }

        GLCall c = new GLCall(index,
                                startTime,
                                traceFileOffset,
                                formattedMsg,
                                msg.getFunction(),
                                msg.hasFb(),
                                msg.getContextId(),
                                msg.getDuration(),
                                msg.getThreadtime());

        addProperties(c, msg);

        try {
            c.setStateTransformations(StateTransformFactory.getTransformsFor(msg));
        } catch (Exception e) {
            c.setStateTransformationCreationError(e.getMessage());
            GlTracePlugin.getDefault().logMessage("Error while creating transformations for "
                                                        + c.toString() + ":");
            GlTracePlugin.getDefault().logMessage(e.getMessage());
        }

        mGLCalls.add(c);
        mGLContextIds.add(Integer.valueOf(c.getContextId()));
    }

    /** Save important values from the {@link GLMessage} in the {@link GLCall} as properties. */
    private void addProperties(GLCall c, GLMessage msg) {
        switch (msg.getFunction()) {
        case glPushGroupMarkerEXT:
            // void PushGroupMarkerEXT(sizei length, const char *marker);
            // save the marker name
            c.addProperty(GLCall.PROPERTY_MARKERNAME,
                    msg.getArgs(1).getCharValue(0).toStringUtf8());
            break;
        case glVertexAttribPointerData:
            // void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
            //         GLboolean normalized, GLsizei stride, const GLvoid* ptr,
            //         int minIndex, int maxIndex)
            c.addProperty(GLCall.PROPERTY_VERTEX_ATTRIB_POINTER_SIZE,
                    Integer.valueOf(msg.getArgs(1).getIntValue(0)));
            c.addProperty(GLCall.PROPERTY_VERTEX_ATTRIB_POINTER_TYPE,
                    GLEnum.valueOf(msg.getArgs(2).getIntValue(0)));
            c.addProperty(GLCall.PROPERTY_VERTEX_ATTRIB_POINTER_DATA,
                    msg.getArgs(5).getRawBytes(0).toByteArray());
            break;
        default:
            break;
        }
    }

    /**
     * Parse the entire file and create a {@link GLTrace} object that can be retrieved
     * using {@link #getTrace()}.
     */
    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException,
            InterruptedException {
        long fileLength;
        try {
            fileLength = mFile.length();
        } catch (IOException e1) {
            fileLength = 0;
        }

        monitor.beginTask("Parsing OpenGL Trace File",
                fileLength > 0 ? 100 : IProgressMonitor.UNKNOWN);

        List<GLFrame> glFrames = null;

        try {
            GLMessage msg = null;
            int msgCount = 0;
            long filePointer = mFile.getFilePointer();
            int percentParsed = 0;

            // counters that maintain some statistics about the trace messages
            long minTraceStartTime = Long.MAX_VALUE;

            while ((msg = sReader.getMessageAtOffset(mFile, -1)) != null) {
                if (minTraceStartTime > msg.getStartTime()) {
                    minTraceStartTime = msg.getStartTime();
                }

                addMessage(msgCount, filePointer, msg, msg.getStartTime() - minTraceStartTime);

                filePointer = mFile.getFilePointer();
                msgCount++;

                if (monitor.isCanceled()) {
                    throw new InterruptedException();
                }

                if (fileLength > 0) {
                    int percentParsedNow = (int)((filePointer * 100) / fileLength);
                    monitor.worked(percentParsedNow - percentParsed);
                    percentParsed = percentParsedNow;
                }
            }

            if (mGLContextIds.size() > 1) {
                // if there are multiple contexts, then the calls may arrive at the
                // host out of order. So we perform a sort based on the invocation time.
                Collections.sort(mGLCalls, new Comparator<GLCall>() {
                    @Override
                    public int compare(GLCall c1, GLCall c2) {
                        long diff = (c1.getStartTime() - c2.getStartTime());

                        // We could return diff casted to an int. But in Java, casting
                        // from a long to an int truncates the bits and will not preserve
                        // the sign. So we resort to comparing the diff to 0 and returning
                        // the sign.
                        if (diff == 0) {
                            return 0;
                        } else if (diff > 0) {
                            return 1;
                        } else {
                            return -1;
                        }
                    }
                });

                // reassign indices after sorting
                for (int i = 0; i < mGLCalls.size(); i++) {
                    mGLCalls.get(i).setIndex(i);
                }
            }

            glFrames = createFrames(mGLCalls);
        } catch (Exception e) {
            throw new InvocationTargetException(e);
        } finally {
            try {
                mFile.close();
            } catch (IOException e) {
                // ignore exception while closing file
            }
            monitor.done();
        }

        File f = new File(mTraceFilePath);
        TraceFileInfo fileInfo = new TraceFileInfo(mTraceFilePath, f.length(), f.lastModified());
        mTrace = new GLTrace(fileInfo, glFrames, mGLCalls, new ArrayList<Integer>(mGLContextIds));
    }

    /** Assign GL calls to GL Frames. */
    private List<GLFrame> createFrames(List<GLCall> calls) {
        List<GLFrame> glFrames = new ArrayList<GLFrame>();
        int startCallIndex = 0;
        int frameIndex = 0;

        for (int i = 0; i < calls.size(); i++) {
            GLCall c = calls.get(i);
            if (c.getFunction() == Function.eglSwapBuffers) {
                glFrames.add(new GLFrame(frameIndex, startCallIndex, i + 1));
                startCallIndex = i + 1;
                frameIndex++;
            }
        }

        // assign left over calls at the end to the last frame
        if (startCallIndex != mGLCalls.size()) {
            glFrames.add(new GLFrame(frameIndex, startCallIndex, mGLCalls.size()));
        }

        return glFrames;
    }

    /**
     * Retrieve the trace object constructed from messages in the trace file.
     */
    public GLTrace getTrace() {
        return mTrace;
    }
}
