// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_next_e2e_test_base.js']);
GEN_INCLUDE(['../testing/mock_feedback.js']);

/**
 * Test fixture for the interactive tutorial.
 */
ChromeVoxTutorialTest = class extends ChromeVoxNextE2ETest {
  /** @override */
  testGenCppIncludes() {
    super.testGenCppIncludes();
    GEN(`
  #include "base/command_line.h"
  #include "ui/accessibility/accessibility_switches.h"
      `);
  }

  /** @override */
  testGenPreamble() {
    GEN(`
    base::CommandLine::ForCurrentProcess()->AppendSwitch(
      ::switches::kEnableExperimentalAccessibilityChromeVoxTutorial);
      `);
    super.testGenPreamble();
  }

  /** @override */
  setUp() {
    window.doCmd = this.doCmd;
  }

  assertActiveLessonIndex(expectedIndex) {
    assertEquals(expectedIndex, this.getPanel().iTutorial.activeLessonIndex);
  }

  assertActiveScreen(expectedScreen) {
    assertEquals(expectedScreen, this.getPanel().iTutorial.activeScreen);
  }

  getPanelWindow() {
    let panelWindow = null;
    while (!panelWindow) {
      panelWindow = chrome.extension.getViews().find(function(view) {
        return view.location.href.indexOf('chromevox/panel/panel.html') > 0;
      });
    }
    return panelWindow;
  }

  getPanel() {
    return this.getPanelWindow().Panel;
  }

  async launchAndWaitForTutorial() {
    assertTrue(this.getPanel().iTutorialEnabled_);
    new PanelCommand(PanelCommandType.TUTORIAL).send();
    await this.waitForTutorial();
    return new Promise(resolve => {
      resolve();
    });
  }

  /**
   * Waits for the interactive tutorial to load.
   */
  async waitForTutorial() {
    return new Promise(resolve => {
      const doc = this.getPanelWindow().document;
      if (doc.getElementById('i-tutorial-container')) {
        resolve();
      } else {
        /**
         * @param {Array<MutationRecord>} mutationsList
         * @param {MutationObserver} observer
         */
        const onMutation = (mutationsList, observer) => {
          for (const mutation of mutationsList) {
            if (mutation.type === 'childList') {
              for (const node of mutation.addedNodes) {
                if (node.id === 'i-tutorial-container') {
                  // Once the tutorial has been added to the document, we need
                  // to wait for the lesson templates to load.
                  const panel = this.getPanel();
                  if (panel.iTutorialReadyForTesting_) {
                    resolve();
                  } else {
                    panel.iTutorial.addEventListener('readyfortesting', () => {
                      resolve();
                    });
                  }
                  observer.disconnect();
                }
              }
            }
          }
        };

        const observer = new MutationObserver(onMutation);
        observer.observe(
            doc.body /* target */, {childList: true} /* options */);
      }
    });
  }

  get simpleDoc() {
    return `
      <p>Some web content</p>
    `;
  }
};

TEST_F('ChromeVoxTutorialTest', 'BasicTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Navigation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Command references', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Sounds and settings', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Resources', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Exit tutorial', 'Button')
        .replay();
  });
});

// Tests that different lessons are shown when choosing an experience from the
// main menu.
TEST_F('ChromeVoxTutorialTest', 'LessonSetTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Quick Orientation Tutorial, [0-9]+ Lessons/)
        .call(doCmd('nextObject'))
        .expectSpeech('Welcome to ChromeVox!')
        .call(() => {
          // Call from the tutorial directly, instead of navigating to and
          // clicking on the main menu button.
          tutorial.showMainMenu();
        })
        .expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(doCmd('nextObject'))
        .expectSpeech('On, Off, and Stop')
        .replay();
  });
});

// Tests that a static lesson does not show the 'Practice area' button.
TEST_F('ChromeVoxTutorialTest', 'NoPracticeAreaTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(() => {
          tutorial.showLesson(0);
        })
        .expectSpeech('On, Off, and Stop', 'Heading 1')
        .call(doCmd('nextButton'))
        .expectSpeech('Next lesson')
        .replay();
  });
});

// Tests that an interactive lesson shows the 'Practice area' button.
TEST_F('ChromeVoxTutorialTest', 'HasPracticeAreaTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Navigation', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Navigation Tutorial, [0-9]+ Lessons/)
        .call(() => {
          tutorial.showLesson(0);
        })
        .expectSpeech('Basic Navigation', 'Heading 1')
        .call(doCmd('nextButton'))
        .expectSpeech('Practice Area')
        .replay();
  });
});

// Tests nudges given in the general tutorial context.
// The first three nudges should read the current item with full context.
// Afterward, general hints will be given about using ChromeVox. Lastly,
// we will give a hint for exiting the tutorial.
TEST_F('ChromeVoxTutorialTest', 'GeneralNudgesTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    const giveNudge = () => {
      tutorial.giveNudge();
    };
    mockFeedback.expectSpeech('Choose your tutorial experience');
    for (let i = 0; i < 3; ++i) {
      mockFeedback.call(giveNudge).expectSpeech(
          'Choose your tutorial experience', 'Heading 1');
    }
    mockFeedback.call(giveNudge)
        .expectSpeech('Hint: Hold Search and press the arrow keys to navigate.')
        .call(giveNudge)
        .expectSpeech(
            'Hint: Press Search + Space to activate the current item.')
        .call(giveNudge)
        .expectSpeech(
            'Hint: Press Escape if you would like to exit this tutorial.')
        .replay();
  });
});

// Tests nudges given in the practice area context. Note, each practice area
// can have different nudge messages; this test confirms that nudges given in
// the practice area differ from those given in the general tutorial context.
TEST_F('ChromeVoxTutorialTest', 'PracticeAreaNudgesTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    const giveNudge = () => {
      tutorial.giveNudge();
    };
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Navigation', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Navigation Tutorial, [0-9]+ Lessons/)
        .call(() => {
          tutorial.showLesson(0);
        })
        .expectSpeech('Basic Navigation', 'Heading 1')
        .call(doCmd('nextButton'))
        .expectSpeech('Practice Area')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('Basic Navigation Practice')
        .call(giveNudge)
        .expectSpeech(
            'Try pressing Search + left/right arrow. The search key is ' +
            'directly above the shift key')
        .call(giveNudge)
        .expectSpeech('Press Search + Space to activate the current item.')
        .replay();
  });
});

// Tests that the tutorial closes when the 'Exit tutorial' button is clicked.
TEST_F('ChromeVoxTutorialTest', 'ExitButtonTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('previousButton'))
        .expectSpeech('Exit tutorial')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('Some web content')
        .replay();
  });
});

// Tests that the tutorial closes when Escape is pressed.
TEST_F('ChromeVoxTutorialTest', 'EscapeTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(() => {
          // Press Escape.
          tutorial.onKeyDown({
            key: 'Escape',
            preventDefault: () => {},
            stopPropagation: () => {}
          });
        })
        .expectSpeech('Some web content')
        .replay();
  });
});

// Tests that the main menu button navigates the user to the main menu screen.
TEST_F('ChromeVoxTutorialTest', 'MainMenuButton', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(this.assertActiveScreen.bind(this, 'main_menu'))
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(this.assertActiveScreen.bind(this, 'lesson_menu'))
        .call(doCmd('previousButton'))
        .expectSpeech('Exit tutorial')
        .call(doCmd('previousButton'))
        .expectSpeech('Main menu')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('Choose your tutorial experience')
        .call(this.assertActiveScreen.bind(this, 'main_menu'))
        .replay();
  });
});

// Tests that the all lessons button navigates the user to the lesson menu
// screen.
TEST_F('ChromeVoxTutorialTest', 'AllLessonsButton', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(this.assertActiveScreen.bind(this, 'main_menu'))
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(this.assertActiveScreen.bind(this, 'lesson_menu'))
        .call(doCmd('nextObject'))
        .expectSpeech('On, Off, and Stop', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('On, Off, and Stop', 'Heading 1')
        .call(this.assertActiveScreen.bind(this, 'lesson'))
        .call(doCmd('nextButton'))
        .expectSpeech('Next lesson')
        .call(doCmd('nextButton'))
        .expectSpeech('All lessons')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(this.assertActiveScreen.bind(this, 'lesson_menu'))
        .replay();
  });
});

// Tests that the next and previous lesson buttons navigate properly.
TEST_F('ChromeVoxTutorialTest', 'NextPreviousButtons', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(() => {
          tutorial.curriculum = 'essential_keys';
          tutorial.showLesson(0);
          this.assertActiveLessonIndex(0);
          this.assertActiveScreen('lesson');
        })
        .expectSpeech('On, Off, and Stop', 'Heading 1')
        .call(doCmd('nextButton'))
        .expectSpeech('Next lesson')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('The ChromeVox modifier key', 'Heading 1')
        .call(this.assertActiveLessonIndex.bind(this, 1))
        .call(doCmd('nextButton'))
        .expectSpeech('Previous lesson')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('On, Off, and Stop', 'Heading 1')
        .call(this.assertActiveLessonIndex.bind(this, 0))
        .replay();
  });
});

// Tests that the title of an interactive lesson is read when shown.
TEST_F('ChromeVoxTutorialTest', 'AutoReadTitle', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Quick Orientation Tutorial, [0-9]+ Lessons/)
        .call(doCmd('nextObject'))
        .expectSpeech('Welcome to ChromeVox!', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech('Welcome to ChromeVox!')
        .expectSpeech(
            'Welcome to the ChromeVox tutorial. To exit this tutorial at any ' +
            'time, press the Escape key on the top left corner of the ' +
            'keyboard. To turn off ChromeVox, hold Control and Alt, and ' +
            `press Z. When you're ready, use the spacebar to move to the ` +
            'next lesson.')
        .replay();
  });
});

// Tests that the content of a non-interactive lesson is read when shown.
TEST_F('ChromeVoxTutorialTest', 'AutoReadLesson', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation', 'Button')
        .call(doCmd('nextObject'))
        .expectSpeech('Essential keys', 'Button')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
        .call(() => {
          tutorial.showLesson(0);
        })
        .expectSpeech('On, Off, and Stop', 'Heading 1')
        .expectSpeech(
            'To temporarily stop ChromeVox from speaking, ' +
            'press the Control key.')
        .expectSpeech('To turn ChromeVox on or off, use Control+Alt+Z.')
        .replay();
  });
});

// Tests for correct speech and earcons on the earcons lesson.
TEST_F('ChromeVoxTutorialTest', 'EarconLesson', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    const nextObjectAndExpectSpeechAndEarcon = (speech, earcon) => {
      mockFeedback.call(doCmd('nextObject'))
          .expectSpeech(speech)
          .expectEarcon(earcon);
    };
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(() => {
          // Show the lesson.
          tutorial.curriculum = 'sounds_and_settings';
          tutorial.showLesson(0);
        })
        .expectSpeech('Sounds')
        .call(doCmd('nextObject'))
        .expectSpeech(new RegExp(
            'ChromeVox uses sounds to give you essential and additional ' +
            'information.'));
    nextObjectAndExpectSpeechAndEarcon('A modal alert', Earcon.ALERT_MODAL);
    nextObjectAndExpectSpeechAndEarcon(
        'A non modal alert', Earcon.ALERT_NONMODAL);
    nextObjectAndExpectSpeechAndEarcon('A button', Earcon.BUTTON);
    mockFeedback.replay();
  });
});

// Tests that a lesson from the quick orientation blocks ChromeVox execution
// until the specified keystroke is pressed.
TEST_F('ChromeVoxTutorialTest', 'QuickOrientationLessonTest', function() {
  const mockFeedback = this.createMockFeedback();
  this.runWithLoadedTree(this.simpleDoc, async function(root) {
    await this.launchAndWaitForTutorial();
    const tutorial = this.getPanel().iTutorial;
    const keyboardHandler = ChromeVoxState.instance.keyboardHandler_;

    // Helper functions. For this test, activate commands by hooking into the
    // BackgroundKeyboardHandler. This is necessary because UserActionMonitor
    // intercepts key sequences before they are routed to CommandHandler.
    const getRangeStartNode = () => {
      return ChromeVoxState.instance.getCurrentRange().start.node;
    };

    const simulateKeyPress = (keyCode, opt_modifiers) => {
      const keyEvent = TestUtils.createMockKeyEvent(keyCode, opt_modifiers);
      keyboardHandler.onKeyDown(keyEvent);
      keyboardHandler.onKeyUp(keyEvent);
    };

    let firstLessonNode;
    mockFeedback.expectSpeech('Choose your tutorial experience')
        .call(doCmd('nextObject'))
        .expectSpeech('Quick orientation')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Quick Orientation Tutorial, [0-9]+ Lessons/)
        .call(doCmd('nextObject'))
        .expectSpeech('Welcome to ChromeVox!')
        .call(doCmd('forceClickOnCurrentItem'))
        .expectSpeech(/Welcome to the ChromeVox tutorial./)
        .call(() => {
          assertEquals(0, tutorial.activeLessonNum);
          firstLessonNode = getRangeStartNode();
        })
        .call(simulateKeyPress.bind(this, KeyCode.RIGHT, {searchKeyHeld: true}))
        .call(() => {
          assertEquals(firstLessonNode, getRangeStartNode());
          assertEquals(0, tutorial.activeLessonNum);
        })
        .call(simulateKeyPress.bind(this, KeyCode.LEFT, {searchKeyHeld: true}))
        .call(() => {
          assertEquals(firstLessonNode, getRangeStartNode());
          assertEquals(0, tutorial.activeLessonNum);
        })
        // Pressing space, which is the desired key sequence, should move us to
        // the next lesson.
        .call(simulateKeyPress.bind(this, KeyCode.SPACE, {}))
        .expectSpeech('Essential Keys: Control')
        .expectSpeech(/Let's start with a few keys you'll use regularly:/)
        .call(() => {
          assertEquals(1, tutorial.activeLessonNum);
          assertNotEquals(firstLessonNode, getRangeStartNode());
        })
        // Pressing control, which is the desired key sequence, should move us
        // to the next lesson.
        .call(simulateKeyPress.bind(this, KeyCode.CONTROL, {}))
        .expectSpeech('Essential Keys: Shift')
        .call(() => {
          assertEquals(2, tutorial.activeLessonNum);
        })
        .replay();
  });
});
