/*
 * Copyright (C) 2018 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.server.wm.flicker;

import android.platform.helpers.IAppHelper;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.util.Rational;
import android.view.Surface;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Tests to help debug individual transitions, capture video recordings and create test cases.
 */
@Ignore("Used for debugging transitions used in FlickerTests.")
@RunWith(AndroidJUnit4.class)
public class DebugTest {
    private IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
            "com.android.server.wm.flicker.testapp", "SimpleApp");
    private UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

    /**
     * atest FlickerTest:DebugTests#openAppCold
     */
    @Test
    public void openAppCold() {
        CommonTransitions.getOpenAppCold(testApp, uiDevice).recordAllRuns().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#openAppWarm
     */
    @Test
    public void openAppWarm() {
        CommonTransitions.openAppWarm(testApp, uiDevice).recordAllRuns().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#changeOrientationFromNaturalToLeft
     */
    @Test
    public void changeOrientationFromNaturalToLeft() {
        CommonTransitions.changeAppRotation(testApp, uiDevice, Surface.ROTATION_0,
                Surface.ROTATION_270).recordAllRuns().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#closeAppWithBackKey
     */
    @Test
    public void closeAppWithBackKey() {
        CommonTransitions.closeAppWithBackKey(testApp, uiDevice).recordAllRuns().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#closeAppWithHomeKey
     */
    @Test
    public void closeAppWithHomeKey() {
        CommonTransitions.closeAppWithHomeKey(testApp, uiDevice).recordAllRuns().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#openAppToSplitScreen
     */
    @Test
    public void openAppToSplitScreen() {
        CommonTransitions.appToSplitScreen(testApp, uiDevice).includeJankyRuns().recordAllRuns()
                .build().run();
    }

    /**
     * atest FlickerTest:DebugTests#splitScreenToLauncher
     */
    @Test
    public void splitScreenToLauncher() {
        CommonTransitions.splitScreenToLauncher(testApp,
                uiDevice).includeJankyRuns().recordAllRuns()
                .build().run();
    }

    /**
     * atest FlickerTest:DebugTests#resizeSplitScreen
     */
    @Test
    public void resizeSplitScreen() {
        IAppHelper bottomApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
                "com.android.server.wm.flicker.testapp", "ImeApp");
        CommonTransitions.resizeSplitScreen(testApp, bottomApp, uiDevice, new Rational(1, 3),
                new Rational(2, 3)).includeJankyRuns().recordEachRun().build().run();
    }

    // IME tests

    /**
     * atest FlickerTest:DebugTests#editTextSetFocus
     */
    @Test
    public void editTextSetFocus() {
        CommonTransitions.editTextSetFocus(uiDevice).includeJankyRuns().recordEachRun()
                .build().run();
    }

    /**
     * atest FlickerTest:DebugTests#editTextLoseFocusToHome
     */
    @Test
    public void editTextLoseFocusToHome() {
        CommonTransitions.editTextLoseFocusToHome(uiDevice).includeJankyRuns().recordEachRun()
                .build().run();
    }

    /**
     * atest FlickerTest:DebugTests#editTextLoseFocusToApp
     */
    @Test
    public void editTextLoseFocusToApp() {
        CommonTransitions.editTextLoseFocusToHome(uiDevice).includeJankyRuns().recordEachRun()
                .build().run();
    }

    // PIP tests

    /**
     * atest FlickerTest:DebugTests#enterPipMode
     */
    @Test
    public void enterPipMode() {
        CommonTransitions.enterPipMode(uiDevice).includeJankyRuns().recordEachRun().build().run();
    }

    /**
     * atest FlickerTest:DebugTests#exitPipModeToHome
     */
    @Test
    public void exitPipModeToHome() {
        CommonTransitions.exitPipModeToHome(uiDevice).includeJankyRuns().recordEachRun()
                .build().run();
    }

    /**
     * atest FlickerTest:DebugTests#exitPipModeToApp
     */
    @Test
    public void exitPipModeToApp() {
        CommonTransitions.exitPipModeToApp(uiDevice).includeJankyRuns().recordEachRun()
                .build().run();
    }
}
