/*
 * 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.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Client;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IDevice.DeviceUnixSocketNamespace;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
import com.android.ide.eclipse.gltrace.editors.GLFunctionTraceViewer;
import com.google.common.io.Closeables;
import com.google.common.util.concurrent.SimpleTimeLimiter;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.ide.IDE;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
    /** Abstract Unix Domain Socket Name used by the gltrace device code. */
    private static final String GLTRACE_UDS = "gltrace";        //$NON-NLS-1$

    /** Local port that is forwarded to the device's {@link #GLTRACE_UDS} socket. */
    private static final int LOCAL_FORWARDED_PORT = 6039;

    /** Activity name to use for a system activity that has already been launched. */
    private static final String SYSTEM_APP = "system";          //$NON-NLS-1$

    /** Time to wait for the application to launch (seconds) */
    private static final int LAUNCH_TIMEOUT = 15;

    /** Time to wait for the application to die (seconds) */
    private static final int KILL_TIMEOUT = 5;

    private static final int MIN_API_LEVEL = 16;

    @Override
    public void run(IAction action) {
        connectToDevice();
    }

    @Override
    public void selectionChanged(IAction action, ISelection selection) {
    }

    @Override
    public void dispose() {
    }

    @Override
    public void init(IWorkbenchWindow window) {
    }

    private void connectToDevice() {
        Shell shell = Display.getDefault().getActiveShell();
        GLTraceOptionsDialog dlg = new GLTraceOptionsDialog(shell);
        if (dlg.open() != Window.OK) {
            return;
        }

        TraceOptions traceOptions = dlg.getTraceOptions();

        IDevice device = getDevice(traceOptions.device);
        String apiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL);
        int apiLevel;
        try {
            apiLevel = Integer.parseInt(apiLevelString);
        } catch (NumberFormatException e) {
            apiLevel = MIN_API_LEVEL;
        }
        if (apiLevel < MIN_API_LEVEL) {
            MessageDialog.openError(shell, "GL Trace",
                    String.format("OpenGL Tracing is only supported on devices at API Level %1$d."
                            + "The selected device '%2$s' provides API level %3$s.",
                                    MIN_API_LEVEL, traceOptions.device, apiLevelString));
            return;
        }

        try {
            setupForwarding(device, LOCAL_FORWARDED_PORT);
        } catch (Exception e) {
            MessageDialog.openError(shell, "Setup GL Trace",
                    "Error while setting up port forwarding: " + e.getMessage());
            return;
        }

        try {
            if (!SYSTEM_APP.equals(traceOptions.appToTrace)) {
                startActivity(device, traceOptions.appToTrace, traceOptions.activityToTrace,
                        traceOptions.isActivityNameFullyQualified);
            }
        } catch (Exception e) {
            MessageDialog.openError(shell, "Setup GL Trace",
                    "Error while launching application: " + e.getMessage());
            return;
        }

        // if everything went well, the app should now be waiting for the gl debugger
        // to connect
        startTracing(shell, traceOptions, LOCAL_FORWARDED_PORT);

        // once tracing is complete, remove port forwarding
        disablePortForwarding(device, LOCAL_FORWARDED_PORT);

        // and finally open the editor to view the file
        openInEditor(shell, traceOptions.traceDestination);
    }

    public static void openInEditor(Shell shell, String traceFilePath) {
        final IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(traceFilePath));
        if (!fileStore.fetchInfo().exists()) {
            return;
        }

        final IWorkbench workbench = PlatformUI.getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        if (window == null) {
            return;
        }

        IWorkbenchPage page = window.getActivePage();
        if (page == null) {
            return;
        }

        try {
            workbench.showPerspective("com.android.ide.eclipse.gltrace.perspective", window);
        } catch (WorkbenchException e) {
        }

        // if there is a editor already open, then refresh its model
        GLFunctionTraceViewer viewer = getOpenTraceViewer(page, traceFilePath);
        if (viewer != null) {
            viewer.setInput(shell, traceFilePath);
        }

        // open the editor (if not open), or bring it to foreground if it is already open
        try {
            IDE.openEditorOnFileStore(page, fileStore);
        } catch (PartInitException e) {
            GlTracePlugin.getDefault().logMessage(
                    "Unexpected error while opening gltrace file in editor: " + e);
            return;
        }
    }

    /**
     * Returns the editor part that has the provided file path open.
     * @param page page containing editors
     * @param traceFilePath file that should be open in an editor
     * @return if given trace file is already open, then a reference to that editor part,
     *         null otherwise
     */
    private static GLFunctionTraceViewer getOpenTraceViewer(IWorkbenchPage page,
            String traceFilePath) {
        IEditorReference[] editorRefs = page.getEditorReferences();
        for (IEditorReference ref : editorRefs) {
            String id = ref.getId();
            if (!GLFunctionTraceViewer.ID.equals(id)) {
                continue;
            }

            IEditorInput input = null;
            try {
                input = ref.getEditorInput();
            } catch (PartInitException e) {
                continue;
            }

            if (!(input instanceof IURIEditorInput)) {
                continue;
            }

            if (traceFilePath.equals(((IURIEditorInput) input).getURI().getPath())) {
                return (GLFunctionTraceViewer) ref.getEditor(true);
            }
        }

        return null;
    }

    @SuppressWarnings("resource") // Closeables.closeQuietly
    public static void startTracing(Shell shell, TraceOptions traceOptions, int port) {
        Socket socket = new Socket();
        DataInputStream traceDataStream = null;
        DataOutputStream traceCommandsStream = null;
        try {
            socket.connect(new java.net.InetSocketAddress("127.0.0.1", port)); //$NON-NLS-1$
            socket.setTcpNoDelay(true);
            traceDataStream = new DataInputStream(socket.getInputStream());
            traceCommandsStream = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            MessageDialog.openError(shell,
                    "OpenGL Trace",
                    "Unable to connect to remote GL Trace Server: " + e.getMessage());
            return;
        }

        // create channel to send trace commands to device
        TraceCommandWriter traceCommandWriter = new TraceCommandWriter(traceCommandsStream);
        try {
            traceCommandWriter.setTraceOptions(traceOptions.collectFbOnEglSwap,
                    traceOptions.collectFbOnGlDraw,
                    traceOptions.collectTextureData);
        } catch (IOException e) {
            MessageDialog.openError(shell,
                    "OpenGL Trace",
                    "Unexpected error while setting trace options: " + e.getMessage());
            closeSocket(socket);
            return;
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(traceOptions.traceDestination, false);
        } catch (FileNotFoundException e) {
            // input path is valid, so this cannot occur
        }

        // create trace writer that writes to a trace file
        TraceFileWriter traceFileWriter = new TraceFileWriter(fos, traceDataStream);
        traceFileWriter.start();

        GLTraceCollectorDialog dlg = new GLTraceCollectorDialog(shell,
                traceFileWriter,
                traceCommandWriter,
                traceOptions);
        dlg.open();

        traceFileWriter.stopTracing();
        traceCommandWriter.close();
        closeSocket(socket);
    }

    private static void closeSocket(Socket socket) {
        try {
            socket.close();
        } catch (IOException e) {
            // ignore error while closing socket
        }
    }

    private void startActivity(IDevice device, String appPackage, String activity,
            boolean isActivityNameFullyQualified)
            throws TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException, IOException, InterruptedException {
        killApp(device, appPackage); // kill app if it is already running
        waitUntilAppKilled(device, appPackage, KILL_TIMEOUT);

        StringBuilder activityPath = new StringBuilder(appPackage);
        if (!activity.isEmpty()) {
            activityPath.append('/');
            if (!isActivityNameFullyQualified) {
                activityPath.append('.');
            }
            activityPath.append(activity);
        }
        String startAppCmd = String.format(
                "am start --opengl-trace %s -a android.intent.action.MAIN -c android.intent.category.LAUNCHER", //$NON-NLS-1$
                activityPath.toString());

        Semaphore launchCompletionSempahore = new Semaphore(0);
        StartActivityOutputReceiver receiver = new StartActivityOutputReceiver(
                launchCompletionSempahore);
        device.executeShellCommand(startAppCmd, receiver);

        // wait until shell finishes launch command
        launchCompletionSempahore.acquire();

        // throw exception if there was an error during launch
        String output = receiver.getOutput();
        if (output.contains("Error")) {             //$NON-NLS-1$
            throw new RuntimeException(output);
        }

        // wait until the app itself has been launched
        waitUntilAppLaunched(device, appPackage, LAUNCH_TIMEOUT);
    }

    private void killApp(IDevice device, String appName) {
        Client client = device.getClient(appName);
        if (client != null) {
            client.kill();
        }
    }

    private void waitUntilAppLaunched(final IDevice device, final String appName, int timeout) {
        Callable<Boolean> c = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                Client client;
                do {
                    client = device.getClient(appName);
                } while (client == null);

                return Boolean.TRUE;
            }
        };
        try {
            new SimpleTimeLimiter().callWithTimeout(c, timeout, TimeUnit.SECONDS, true);
        } catch (Exception e) {
            throw new RuntimeException("Timed out waiting for application to launch.");
        }

        // once the app has launched, wait an additional couple of seconds
        // for it to start up
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // ignore
        }
    }

    private void waitUntilAppKilled(final IDevice device, final String appName, int timeout) {
        Callable<Boolean> c = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                Client client;
                while ((client = device.getClient(appName)) != null) {
                    client.kill();
                }
                return Boolean.TRUE;
            }
        };
        try {
            new SimpleTimeLimiter().callWithTimeout(c, timeout, TimeUnit.SECONDS, true);
        } catch (Exception e) {
            throw new RuntimeException("Timed out waiting for running application to die.");
        }
    }

    public static void setupForwarding(IDevice device, int i)
            throws TimeoutException, AdbCommandRejectedException, IOException {
        device.createForward(i, GLTRACE_UDS, DeviceUnixSocketNamespace.ABSTRACT);
    }

    public static void disablePortForwarding(IDevice device, int port) {
        try {
            device.removeForward(port, GLTRACE_UDS, DeviceUnixSocketNamespace.ABSTRACT);
        } catch (Exception e) {
            // ignore exceptions;
        }
    }

    private IDevice getDevice(String deviceName) {
        IDevice[] devices = AndroidDebugBridge.getBridge().getDevices();

        for (IDevice device : devices) {
            if (device.getName().equals(deviceName)) {
                return device;
            }
        }

        return null;
    }

    private static class StartActivityOutputReceiver implements IShellOutputReceiver {
        private Semaphore mSemaphore;
        private StringBuffer sb = new StringBuffer(300);

        public StartActivityOutputReceiver(Semaphore s) {
            mSemaphore = s;
        }

        @Override
        public void addOutput(byte[] data, int offset, int length) {
            String d = new String(data, offset, length);
            sb.append(d);
        }

        @Override
        public void flush() {
            mSemaphore.release();
        }

        @Override
        public boolean isCancelled() {
            return false;
        }

        public String getOutput() {
            return sb.toString();
        }
    }
}
