// Copyright 2017 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.

import 'dart:convert' show BASE64;
import 'package:stack_trace/stack_trace.dart' show Chain;

import 'by.dart' show byToJson;
import 'keyboard.dart';
import 'logs.dart';
import 'mouse.dart';
import 'navigation.dart';
import 'target_locator.dart';
import 'timeouts.dart';
import 'web_element.dart';
import 'window.dart';

import '../common_spec/cookies.dart';

import '../command_event.dart';
import '../command_processor.dart';
import '../common.dart';
import '../navigation.dart';
import '../target_locator.dart';
import '../timeouts.dart';
import '../web_driver.dart';
import '../web_element.dart';
import '../window.dart';

class JsonWireWebDriver implements WebDriver, SearchContext {
  final CommandProcessor _commandProcessor;
  final Uri _prefix;
  final Map<String, dynamic> capabilities;
  final String id;
  final Uri uri;
  final bool filterStackTraces;

  @override
  bool notifyListeners = true;

  final _commandListeners = new List<WebDriverListener>();

  JsonWireWebDriver(
      this._commandProcessor, Uri uri, String id, this.capabilities,
      {this.filterStackTraces: true})
      : this.uri = uri,
        this.id = id,
        this._prefix = uri.resolve('session/$id/');

  @override
  void addEventListener(WebDriverListener listener) =>
      _commandListeners.add(listener);

  @override
  String get currentUrl => getRequest('url') as String;

  @override
  void get(/* Uri | String */ url) {
    final urlStr = (url is Uri) ? url.toString() : url;
    postRequest('url', {'url': urlStr as String});
  }

  @override
  String get title => getRequest('title') as String;

  @override
  List<WebElement> findElements(By by) {
    final elements = postRequest('elements', byToJson(by));
    int i = 0;

    final webElements = new List<JsonWireWebElement>();
    for (final element in elements) {
      webElements.add(new JsonWireWebElement(
          this, element[jsonWireElementStr], this, by, i++));
    }
    return webElements;
  }

  @override
  WebElement findElement(By by) {
    final element = postRequest('element', byToJson(by));
    return new JsonWireWebElement(this, element[jsonWireElementStr], this, by);
  }

  @override
  String get pageSource => getRequest('source') as String;

  @override
  void close() {
    deleteRequest('window');
  }

  @override
  void quit({bool closeSession: true}) {
    try {
      if (closeSession) {
        _commandProcessor.delete(uri.resolve('session/$id'));
      }
    } finally {
      _commandProcessor.close();
    }
  }

  @override
  List<Window> get windows => new JsonWireWindows(this).allWindows;

  @override
  Window get window => new JsonWireWindows(this).activeWindow;

  @override
  WebElement get activeElement {
    final element = postRequest('element/active');
    if (element != null) {
      return new JsonWireWebElement(
          this, element[jsonWireElementStr], this, 'activeElement');
    }
    return null;
  }

  @override
  Windows get windowsManager => new JsonWireWindows(this);

  @override
  TargetLocator get switchTo => new JsonWireTargetLocator(this);

  @override
  Navigation get navigate => new JsonWireNavigation(this);

  @override
  Cookies get cookies => new Cookies(this);

  @override
  Logs get logs => new Logs(this);

  @override
  Timeouts get timeouts => new JsonWireTimeouts(this);

  @override
  Keyboard get keyboard => new Keyboard(this);

  @override
  Mouse get mouse => new Mouse(this);

  @override
  String captureScreenshotAsBase64() => getRequest('screenshot');

  @override
  List<int> captureScreenshotAsList() {
    final base64Encoded = captureScreenshotAsBase64();
    return BASE64.decode(base64Encoded);
  }

  @override
  dynamic executeAsync(String script, List args) => _recursiveElementify(
      postRequest('execute_async', {'script': script, 'args': args}));

  @override
  dynamic execute(String script, List args) => _recursiveElementify(
      postRequest('execute', {'script': script, 'args': args}));

  dynamic _recursiveElementify(result) {
    if (result is Map) {
      if (result.length == 1 && result.containsKey(jsonWireElementStr)) {
        return new JsonWireWebElement(
            this, result[jsonWireElementStr], this, 'javascript');
      } else {
        final newResult = {};
        result.forEach((key, value) {
          newResult[key] = _recursiveElementify(value);
        });
        return newResult;
      }
    } else if (result is List) {
      return result.map((value) => _recursiveElementify(value)).toList();
    } else {
      return result;
    }
  }

  @override
  dynamic postRequest(String command, [params]) => _performRequestWithLog(
      () => _commandProcessor.post(_resolve(command), params),
      'POST',
      command,
      params);

  @override
  dynamic getRequest(String command) => _performRequestWithLog(
      () => _commandProcessor.get(_resolve(command)), 'GET', command, null);

  @override
  dynamic deleteRequest(String command) => _performRequestWithLog(
      () => _commandProcessor.delete(_resolve(command)),
      'DELETE',
      command,
      null);

  // Performs request and sends the result to listeners/onCommandController.
  // This is typically always what you want to use.
  dynamic _performRequestWithLog(
      Function fn, String method, String command, params) {
    return _performRequest(fn, method, command, params);
  }

  // Performs the request. This will not notify any listeners or
  // onCommandController. This should only be called from
  // _performRequestWithLog.
  dynamic _performRequest(Function fn, String method, String command, params) {
    final startTime = new DateTime.now();
    var trace = new Chain.current();
    if (filterStackTraces) {
      trace = trace.foldFrames(
          (f) => f.library.startsWith('package:webdriver/'),
          terse: true);
    }
    var result;
    var exception;
    try {
      result = fn();
      return result;
    } catch (e) {
      exception = e;
      rethrow;
    } finally {
      if (notifyListeners) {
        for (WebDriverListener listener in _commandListeners) {
          listener(new WebDriverCommandEvent(
              method: method,
              endPoint: command,
              params: params,
              startTime: startTime,
              endTime: new DateTime.now(),
              exception: exception,
              result: result,
              stackTrace: trace));
        }
      }
    }
  }

  Uri _resolve(String command) {
    var uri = _prefix.resolve(command);
    if (uri.path.endsWith('/')) {
      uri = uri.replace(path: uri.path.substring(0, uri.path.length - 1));
    }
    return uri;
  }

  @override
  WebDriver get driver => this;

  @override
  String toString() => 'JsonWireWebDriver($_prefix)';
}
