// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

@TestOn("vm")
library webdriver.support.forwarder_test;

import 'dart:io';

import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:webdriver/io.dart';
import 'package:webdriver/support/forwarder.dart';

import '../io_config.dart' as config;
import '../test_util.dart' as test_util;

const buttonClicked = 'Button clicked';
const buttonNotClicked = 'Button not clicked';

void main() {
  config.config();

  group('WebDriverForwarder', () {
    WebDriver driver;
    WebDriverForwarder forwarder;
    HttpServer server;
    WebDriver forwardedDriver;
    Uri address;

    setUp(() async {
      driver = await test_util.createTestDriver();
      ;
      forwarder =
          new WebDriverForwarder(driver, prefix: '/webdriver/session/1');

      server = await HttpServer.bind(InternetAddress.ANY_IP_V4, 0);
      server.listen((request) {
        if (request.uri.path.startsWith('/webdriver')) {
          forwarder.forward(request);
        } else if (request.method == 'GET' &&
            request.uri.path.endsWith('test_page.html')) {
          File file = new File(
              path.join('test', 'support', 'forwarder_test_page.html'));
          request.response
            ..statusCode = HttpStatus.OK
            ..headers.set('Content-type', 'text/html');
          file.openRead().pipe(request.response);
        } else {
          request.response
            ..statusCode = HttpStatus.NOT_FOUND
            ..close();
        }
      });
      address = new Uri.http('localhost:${server.port}', '/webdriver/');
      forwardedDriver = await fromExistingSession('1', uri: address);

      await forwardedDriver.get(address.resolve('/test_page.html'));
    });

    tearDown(() async {
      try {
        await forwardedDriver.quit();
      } catch (e) {
        print('Error quitting forwardedDriver: $e');
      }
      try {
        await server.close(force: true);
      } catch (e) {
        print('Error quitting server: $e');
      }
    });

    test('get url', () async {
      expect(await forwardedDriver.currentUrl, endsWith('test_page.html'));
    });

    test('click button', () async {
      expect(await forwardedDriver.getRequest('element/div/text'),
          buttonNotClicked);

      await forwardedDriver.postRequest('element/button/click', {'button': 0});
      expect(
          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
    });

    test('moveto/click', () async {
      expect(await forwardedDriver.getRequest('element/div/text'),
          buttonNotClicked);

      await forwardedDriver.postRequest('moveto', {'element': 'button'});
      await forwardedDriver.mouse.click();

      expect(
          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
    });

    test('execute_script', () async {
      expect(await forwardedDriver.getRequest('element/div/text'),
          buttonNotClicked);

      await forwardedDriver.execute(
          'arguments[0].el.click();', [{'el': {'ELEMENT': 'button'}}]);

      expect(
          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
    });

    test('element equals', () async {
      expect(
          await forwardedDriver.getRequest('element/div/equals/div'), isTrue);
      expect(await forwardedDriver.getRequest('element/div/equals/button'),
          isFalse);
    });

    // TODO(DrMarcII) add test that actually uses shadow dom
    test('enable/disable deep', () async {
      await forwardedDriver.postRequest('disabledeep');

      expect(await forwardedDriver.getRequest('element/div/text'),
          buttonNotClicked);

      await forwardedDriver.postRequest('element/button/click', {'button': 0});
      expect(
          await forwardedDriver.getRequest('element/div/text'), buttonClicked);

      await forwardedDriver.postRequest('enabledeep');
      await forwardedDriver.navigate.refresh();

      expect(await forwardedDriver.getRequest('element/div/text'),
          buttonNotClicked);

      await forwardedDriver.postRequest('element/button/click', {'button': 0});
      expect(
          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
    });

    test('window close', () async {
      await forwardedDriver.close();
    });
  });
}
