/*
 * Copyright (C) 2012 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.views;

import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
import com.android.ide.eclipse.gltrace.model.GLCall;
import com.android.ide.eclipse.gltrace.model.GLTrace;
import com.android.ide.eclipse.gltrace.widgets.ImageCanvas;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.Page;

import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
 * A {@link FrameSummaryViewPage} displays summary information regarding a frame. This includes
 * the contents of the frame buffer at the end of the frame, and statistics regarding the
 * OpenGL Calls present in the frame.
 */
public class FrameSummaryViewPage extends Page {
    private GLTrace mTrace;

    private final Object mLock = new Object();
    private Job mRefresherJob;
    private int mCurrentFrame;

    private SashForm mSash;
    private ImageCanvas mImageCanvas;

    private Label mWallClockTimeLabel;
    private Label mThreadTimeLabel;

    private TableViewer mStatsTableViewer;
    private StatsLabelProvider mStatsLabelProvider;
    private StatsTableComparator mStatsTableComparator;

    private FitToCanvasAction mFitToCanvasAction;
    private SaveImageAction mSaveImageAction;

    private static final String[] STATS_TABLE_PROPERTIES = {
        "Function",
        "Count",
        "Wall Time (ns)",
        "Thread Time (ns)",
    };
    private static final float[] STATS_TABLE_COLWIDTH_RATIOS = {
        0.4f, 0.1f, 0.25f, 0.25f,
    };
    private static final int[] STATS_TABLE_COL_ALIGNMENT = {
        SWT.LEFT, SWT.LEFT, SWT.RIGHT, SWT.RIGHT,
    };

    public FrameSummaryViewPage(GLTrace trace) {
        mTrace = trace;
    }

    public void setInput(GLTrace trace) {
        mTrace = trace;
    }

    @Override
    public void createControl(Composite parent) {
        mSash = new SashForm(parent, SWT.VERTICAL);

        // create image canvas where the framebuffer is displayed
        mImageCanvas = new ImageCanvas(mSash);

        // create a composite where the frame statistics are displayed
        createFrameStatisticsPart(mSash);

        mSash.setWeights(new int[] {70, 30});

        mFitToCanvasAction = new FitToCanvasAction(true, mImageCanvas);
        mSaveImageAction = new SaveImageAction(mImageCanvas);

        IToolBarManager toolbarManager = getSite().getActionBars().getToolBarManager();
        toolbarManager.add(mFitToCanvasAction);
        toolbarManager.add(mSaveImageAction);
    }

    private void createFrameStatisticsPart(Composite parent) {
        Composite c = new Composite(parent, SWT.NONE);
        c.setLayout(new GridLayout(2, false));
        GridDataFactory.fillDefaults().grab(true, true).applyTo(c);

        Label l = new Label(c, SWT.NONE);
        l.setText("Cumulative call duration of all OpenGL Calls in this frame:");
        l.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
        GridDataFactory.fillDefaults().span(2, 1).applyTo(l);

        l = new Label(c, SWT.NONE);
        l.setText("Wall Clock Time: ");
        GridDataFactory.fillDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(l);

        mWallClockTimeLabel = new Label(c, SWT.NONE);
        GridDataFactory.defaultsFor(mWallClockTimeLabel)
                       .grab(true, false)
                       .applyTo(mWallClockTimeLabel);

        l = new Label(c, SWT.NONE);
        l.setText("Thread Time: ");
        GridDataFactory.fillDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(l);

        mThreadTimeLabel = new Label(c, SWT.NONE);
        GridDataFactory.defaultsFor(mThreadTimeLabel)
                       .grab(true, false)
                       .applyTo(mThreadTimeLabel);

        l = new Label(c, SWT.HORIZONTAL | SWT.SEPARATOR);
        GridDataFactory.fillDefaults().span(2, 1).applyTo(l);

        l = new Label(c, SWT.NONE);
        l.setText("Per OpenGL Function Statistics:");
        l.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
        GridDataFactory.fillDefaults().span(2, 1).applyTo(l);

        final Table table = new Table(c, SWT.BORDER | SWT.FULL_SELECTION);
        GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(table);

        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        mStatsTableViewer = new TableViewer(table);
        mStatsLabelProvider = new StatsLabelProvider();
        mStatsTableComparator = new StatsTableComparator(1);

        // when a column is selected, sort the table based on that column
        SelectionListener columnSelectionListener = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                TableColumn tc = (TableColumn) e.widget;
                String colText = tc.getText();
                for (int i = 0; i < STATS_TABLE_PROPERTIES.length; i++) {
                    if (STATS_TABLE_PROPERTIES[i].equals(colText)) {
                        mStatsTableComparator.setSortColumn(i);
                        table.setSortColumn(tc);
                        table.setSortDirection(mStatsTableComparator.getDirection());
                        mStatsTableViewer.refresh();
                        break;
                    }
                }
            }
        };

        for (int i = 0; i < STATS_TABLE_PROPERTIES.length; i++) {
            TableViewerColumn tvc = new TableViewerColumn(mStatsTableViewer, SWT.NONE);
            tvc.getColumn().setText(STATS_TABLE_PROPERTIES[i]);
            tvc.setLabelProvider(mStatsLabelProvider);
            tvc.getColumn().setAlignment(STATS_TABLE_COL_ALIGNMENT[i]);
            tvc.getColumn().addSelectionListener(columnSelectionListener);
        }
        mStatsTableViewer.setContentProvider(new StatsContentProvider());
        mStatsTableViewer.setInput(null);
        mStatsTableViewer.setComparator(mStatsTableComparator);

        // resize columns appropriately when the size of the widget changes
        table.addControlListener(new ControlAdapter() {
            @Override
            public void controlResized(ControlEvent e) {
                int w = table.getClientArea().width;

                for (int i = 0; i < STATS_TABLE_COLWIDTH_RATIOS.length; i++) {
                    table.getColumn(i).setWidth((int) (w * STATS_TABLE_COLWIDTH_RATIOS[i]));
                }
            }
        });
    }

    @Override
    public Control getControl() {
        return mSash;
    }

    @Override
    public void setFocus() {
    }

    public void setSelectedFrame(int frame) {
        if (mTrace == null) {
            return;
        }

        synchronized (mLock) {
            mCurrentFrame = frame;

            if (mRefresherJob != null) {
                return;
            }

            mRefresherJob = new Job("Update Frame Summary Task") {
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    final int currentFrame;
                    synchronized (mLock) {
                        currentFrame = mCurrentFrame;
                        mRefresherJob = null;
                    };

                    updateImageCanvas(currentFrame);
                    updateFrameStats(currentFrame);

                    return Status.OK_STATUS;
                }
            };
            mRefresherJob.setPriority(Job.SHORT);
            mRefresherJob.schedule(500);
        };
    }

    private void updateFrameStats(int frame) {
        final List<GLCall> calls = mTrace.getGLCallsForFrame(frame);

        Job job = new Job("Update Frame Statistics") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                long wallClockDuration = 0;
                long threadDuration = 0;

                final Map<Function, PerCallStats> cumulativeStats =
                        new EnumMap<Function, PerCallStats>(Function.class);

                for (GLCall c: calls) {
                    wallClockDuration += c.getWallDuration();
                    threadDuration += c.getThreadDuration();

                    PerCallStats stats = cumulativeStats.get(c.getFunction());
                    if (stats == null) {
                        stats = new PerCallStats();
                    }

                    stats.count++;
                    stats.threadDuration += c.getThreadDuration();
                    stats.wallDuration += c.getWallDuration();

                    cumulativeStats.put(c.getFunction(), stats);
                }

                final String wallTime = formatMilliSeconds(wallClockDuration);
                final String threadTime = formatMilliSeconds(threadDuration);

                Display.getDefault().syncExec(new Runnable() {
                    @Override
                    public void run() {
                        mWallClockTimeLabel.setText(wallTime);
                        mThreadTimeLabel.setText(threadTime);
                        mStatsTableViewer.setInput(cumulativeStats);
                    }
                });

                return Status.OK_STATUS;
            }
        };
        job.setUser(true);
        job.schedule();
    }

    private String formatMilliSeconds(long nanoSeconds) {
        double milliSeconds = (double) nanoSeconds / 1000000;
        return String.format("%.2f ms", milliSeconds);          //$NON-NLS-1$
    }

    private void updateImageCanvas(int frame) {
        int lastCallIndex = mTrace.getFrame(frame).getEndIndex() - 1;
        if (lastCallIndex >= 0 && lastCallIndex < mTrace.getGLCalls().size()) {
            GLCall call = mTrace.getGLCalls().get(lastCallIndex);
            final Image image = mTrace.getImage(call);
            Display.getDefault().asyncExec(new Runnable() {
                @Override
                public void run() {
                    mImageCanvas.setImage(image);

                    mFitToCanvasAction.setEnabled(image != null);
                    mSaveImageAction.setEnabled(image != null);
                }
            });
        }
    }

    /** Cumulative stats maintained for each type of OpenGL Function in a particular frame. */
    private static class PerCallStats {
        public int count;
        public long wallDuration;
        public long threadDuration;
    }

    private static class StatsContentProvider implements IStructuredContentProvider {
        @Override
        public void dispose() {
        }

        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }

        @Override
        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof Map<?, ?>) {
                return ((Map<?, ?>) inputElement).entrySet().toArray();
            }

            return null;
        }
    }

    private static class StatsLabelProvider extends ColumnLabelProvider {
        @Override
        public void update(ViewerCell cell) {
            Object element = cell.getElement();
            if (!(element instanceof Map.Entry<?, ?>)) {
                return;
            }

            Function f = (Function) ((Map.Entry<?, ?>) element).getKey();
            PerCallStats stats = (PerCallStats) ((Map.Entry<?, ?>) element).getValue();

            switch (cell.getColumnIndex()) {
            case 0:
                cell.setText(f.toString());
                break;
            case 1:
                cell.setText(Integer.toString(stats.count));
                break;
            case 2:
                cell.setText(formatDuration(stats.wallDuration));
                break;
            case 3:
                cell.setText(formatDuration(stats.threadDuration));
                break;
            default:
                // should not happen
                cell.setText("??"); //$NON-NLS-1$
                break;
            }
        }

        private String formatDuration(long time) {
            // Max duration is in the 10s of milliseconds = xx,xxx,xxx ns
            // So we require a format specifier that is 10 characters wide
            return String.format("%,10d", time);            //$NON-NLS-1$
        }
    }

    private static class StatsTableComparator extends ViewerComparator {
        private int mSortColumn;
        private boolean mDescending = true;

        private StatsTableComparator(int defaultSortColIndex) {
            mSortColumn = defaultSortColIndex;
        }

        public void setSortColumn(int index) {
            if (index == mSortColumn) {
                // if same column as what we are currently sorting on,
                // then toggle the direction
                mDescending = !mDescending;
            } else {
                mSortColumn = index;
                mDescending = true;
            }
        }

        public int getDirection() {
            return mDescending ? SWT.UP : SWT.DOWN;
        }

        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
            Map.Entry<?, ?> entry1;
            Map.Entry<?, ?> entry2;

            if (mDescending) {
                entry1 = (Map.Entry<?, ?>) e1;
                entry2 = (Map.Entry<?, ?>) e2;
            } else {
                entry1 = (Map.Entry<?, ?>) e2;
                entry2 = (Map.Entry<?, ?>) e1;
            }

            String k1 = entry1.getKey().toString();
            String k2 = entry2.getKey().toString();

            PerCallStats stats1 = (PerCallStats) entry1.getValue();
            PerCallStats stats2 = (PerCallStats) entry2.getValue();

            switch (mSortColumn) {
            case 0: // function name
                return String.CASE_INSENSITIVE_ORDER.compare(k1, k2);
            case 1:
                return stats1.count - stats2.count;
            case 2:
                return (int) (stats1.wallDuration - stats2.wallDuration);
            case 3:
                return (int) (stats1.threadDuration - stats2.threadDuration);
            default:
                return super.compare(viewer, e1, e2);
            }
        }
    }
}
