/*
 * 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.commands.uiautomator;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.UiAutomation;
import android.graphics.Point;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Environment;
import android.view.Display;
import android.view.accessibility.AccessibilityNodeInfo;

import com.android.commands.uiautomator.Launcher.Command;
import com.android.uiautomator.core.AccessibilityNodeInfoDumper;
import com.android.uiautomator.core.UiAutomationShellWrapper;

import java.io.File;
import java.util.concurrent.TimeoutException;

/**
 * Implementation of the dump subcommand
 *
 * This creates an XML dump of current UI hierarchy
 */
public class DumpCommand extends Command {

    private static final File DEFAULT_DUMP_FILE = new File(
            Environment.getLegacyExternalStorageDirectory(), "window_dump.xml");

    public DumpCommand() {
        super("dump");
    }

    @Override
    public String shortHelp() {
        return "creates an XML dump of current UI hierarchy";
    }

    @Override
    public String detailedOptions() {
        return "    dump [--verbose][file]\n"
            + "      [--compressed]: dumps compressed layout information.\n"
            + "      [file]: the location where the dumped XML should be stored, default is\n      "
            + DEFAULT_DUMP_FILE.getAbsolutePath() + "\n";
    }

    @Override
    public void run(String[] args) {
        File dumpFile = DEFAULT_DUMP_FILE;
        boolean verboseMode = true;
        boolean allWindows = false;

        for (String arg : args) {
            if (arg.equals("--compressed"))
                verboseMode = false;
            else if (arg.equals("--windows")) {
                allWindows = true;
            } else if (!arg.startsWith("-")) {
                dumpFile = new File(arg);
            }
        }

        UiAutomationShellWrapper automationWrapper = new UiAutomationShellWrapper();
        automationWrapper.connect();
        if (verboseMode) {
            // default
            automationWrapper.setCompressedLayoutHierarchy(false);
        } else {
            automationWrapper.setCompressedLayoutHierarchy(true);
        }

        // It appears that the bridge needs time to be ready. Making calls to the
        // bridge immediately after connecting seems to cause exceptions. So let's also
        // do a wait for idle in case the app is busy.
        try {
            UiAutomation uiAutomation = automationWrapper.getUiAutomation();
            uiAutomation.waitForIdle(1000, 1000 * 10);
            if (allWindows) {
                AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
                info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
                uiAutomation.setServiceInfo(info);
                AccessibilityNodeInfoDumper.dumpWindowsToFile(
                        uiAutomation.getWindowsOnAllDisplays(), dumpFile,
                        DisplayManagerGlobal.getInstance());
            } else {
                AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow();
                if (info == null) {
                    System.err.println("ERROR: null root node returned by UiTestAutomationBridge.");
                    return;
                }

                Display display =
                        DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
                int rotation = display.getRotation();
                Point size = new Point();
                display.getSize(size);
                AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x,
                        size.y);
            }
        } catch (TimeoutException re) {
            System.err.println("ERROR: could not get idle state.");
            return;
        } finally {
            automationWrapper.disconnect();
        }
        System.out.println(
                String.format("UI hierchary dumped to: %s", dumpFile.getAbsolutePath()));
    }
}
