// 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:math' show Point, Rectangle;

import '../../async_core.dart' as async_core;
import '../common/by.dart';
import '../common/request_client.dart';
import '../common/web_element.dart' as common;
import '../common/webdriver_handler.dart';
import 'common.dart';
import 'common_stub.dart' if (dart.library.io) 'common_io.dart';
import 'web_driver.dart';

/// WebDriver representation and interactions with an HTML element.
class WebElement extends common.WebElement implements SearchContext {
  @override
  final String id;

  /// Produces a compatible [async_core.WebElement]. Allows backwards
  /// compatibility with other frameworks.
  async_core.WebElement get asyncElement => createAsyncWebElement(this);

  @override
  async_core.SearchContext get asyncContext => asyncElement;

  /// The context from which this element was found.
  final SearchContext? context;

  @override
  final WebDriver driver;

  final SyncRequestClient _client;

  final WebDriverHandler _handler;

  /// How the element was located from the context.
  final dynamic /* String | Finder */ locator;

  /// The index of this element in the set of element founds. If the method
  /// used to find this element always returns one element, then this is null.
  final int? index;

  WebElement(
    this.driver,
    this._client,
    this._handler,
    this.id, [
    this.context,
    this.locator,
    this.index,
  ]);

  WebElement? get parent {
    final parentId = _parentId;
    if (parentId == null) {
      return null;
    }
    return WebElement(
      driver,
      _client,
      _handler,
      parentId,
    );
  }

  String? get _parentId => _client.send(
        _handler.element.buildPropertyRequest(id, 'parentElement'),
        _handler.elementFinder.parseFindElementResponseCore,
      );

  static final _parentCache = <String, String?>{};

  /// Gets a chain of parent elements, including the element itself.
  List<String> get parents {
    WebElement? p = this;
    final result = <String>[];
    while (p != null) {
      final id = p.id;
      if (_parentCache.containsKey(id)) {
        break;
      }
      result.add(id);
      _parentCache[id] = (p = p.parent)?.id;
    }

    if (p != null) {
      // Hit cache in the previous loop.
      String? id = p.id;
      while (id != null) {
        result.add(id);
        id = _parentCache[id];
      }
    }

    return result;
  }

  /// Click on this element.
  void click() {
    _client.send(_handler.element.buildClickRequest(id),
        _handler.element.parseClickResponse);
  }

  /// Send [keysToSend] to this element.
  void sendKeys(String keysToSend) {
    _client.send(_handler.element.buildSendKeysRequest(id, keysToSend),
        _handler.element.parseSendKeysResponse);
  }

  /// Clear the content of a text element.
  void clear() {
    _client.send(_handler.element.buildClearRequest(id),
        _handler.element.parseClearResponse);
  }

  /// Is this radio button/checkbox selected?
  bool get selected => _client.send(_handler.element.buildSelectedRequest(id),
      _handler.element.parseSelectedResponse);

  /// Is this form element enabled?
  bool get enabled => _client.send(_handler.element.buildEnabledRequest(id),
      _handler.element.parseEnabledResponse);

  /// Is this element visible in the page?
  bool get displayed => _client.send(_handler.element.buildDisplayedRequest(id),
      _handler.element.parseDisplayedResponse);

  /// The location of the element.
  ///
  /// This is assumed to be the upper left corner of the element, but its
  /// implementation is not well defined in the JSON spec.
  Point<int> get location => _client.send(
      _handler.element.buildLocationRequest(id),
      _handler.element.parseLocationResponse);

  /// The size of this element.
  Rectangle<int> get size => _client.send(_handler.element.buildSizeRequest(id),
      _handler.element.parseSizeResponse);

  /// The bounds of this element.
  Rectangle<int> get rect {
    final location = this.location;
    final size = this.size;
    return Rectangle<int>(location.x, location.y, size.width, size.height);
  }

  /// The tag name for this element.
  String get name => _client.send(_handler.element.buildNameRequest(id),
      _handler.element.parseNameResponse);

  ///  Visible text within this element.
  String get text => _client.send(_handler.element.buildTextRequest(id),
      _handler.element.parseTextResponse);

  ///Find an element nested within this element.
  ///
  /// Throws [async_core.NoSuchElementException] if matching element is not
  /// found.
  @override
  WebElement findElement(By by) => WebElement(
      driver,
      _client,
      _handler,
      _client.send(_handler.elementFinder.buildFindElementRequest(by, id),
          _handler.elementFinder.parseFindElementResponse),
      this,
      by);

  /// Find multiple elements nested within this element.
  @override
  List<WebElement> findElements(By by) {
    final ids = _client.send(
        _handler.elementFinder.buildFindElementsRequest(by, id),
        _handler.elementFinder.parseFindElementsResponse);

    final elements = <WebElement>[];
    var i = 0;
    for (final id in ids) {
      elements.add(WebElement(driver, _client, _handler, id, this, by, i++));
    }

    return elements;
  }

  /// Access to the HTML attributes of this tag.
  Attributes get attributes => Attributes((name) => _client.send(
      _handler.element.buildAttributeRequest(id, name),
      _handler.element.parseAttributeResponse));

  /// Access to the HTML properties of this tag.
  Attributes get properties => Attributes((name) => _client.send(
      _handler.element.buildPropertyRequest(id, name),
      _handler.element.parsePropertyResponse));

  /// Access to the cssProperties of this element.
  Attributes get cssProperties => Attributes((name) => _client.send(
      _handler.element.buildCssPropertyRequest(id, name),
      _handler.element.parseCssPropertyResponse));

  /// Are these two elements the same underlying element in the DOM.
  bool equals(WebElement other) => other.driver == driver && other.id == id;

  @override
  int get hashCode => driver.hashCode * 3 + id.hashCode;

  @override
  bool operator ==(Object other) =>
      other is WebElement && other.driver == driver && other.id == id;

  @override
  String toString() {
    final out = StringBuffer()..write(context);
    if (locator is By) {
      if (index == null) {
        out.write('.findElement(');
      } else {
        out.write('.findElements(');
      }
      out
        ..write(locator)
        ..write(')');
    } else {
      out
        ..write('.')
        ..write(locator);
    }
    if (index != null) {
      out
        ..write('[')
        ..write(index)
        ..write(']');
    }
    return out.toString();
  }

  String toStringDeep() => "<$name>\n\nHTML:\n${properties['outerHTML']}";
}
