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

import 'find.dart';
import 'message.dart';

/// A Flutter Driver command that reads the text from a given element.
class GetText extends CommandWithTarget {
  /// [finder] looks for an element that contains a piece of text.
  GetText(SerializableFinder finder, { Duration timeout }) : super(finder, timeout: timeout);

  /// Deserializes this command from the value generated by [serialize].
  GetText.deserialize(Map<String, String> json) : super.deserialize(json);

  @override
  String get kind => 'get_text';
}

/// The result of the [GetText] command.
class GetTextResult extends Result {
  /// Creates a result with the given [text].
  const GetTextResult(this.text);

  /// The text extracted by the [GetText] command.
  final String text;

  /// Deserializes the result from JSON.
  static GetTextResult fromJson(Map<String, dynamic> json) {
    return GetTextResult(json['text'] as String);
  }

  @override
  Map<String, dynamic> toJson() => <String, String>{
    'text': text,
  };
}

/// A Flutter Driver command that enters text into the currently focused widget.
class EnterText extends Command {
  /// Creates a command that enters text into the currently focused widget.
  const EnterText(this.text, { Duration timeout }) : super(timeout: timeout);

  /// Deserializes this command from the value generated by [serialize].
  EnterText.deserialize(Map<String, String> json)
    : text = json['text'],
      super.deserialize(json);

  /// The text extracted by the [GetText] command.
  final String text;

  @override
  String get kind => 'enter_text';

  @override
  Map<String, String> serialize() => super.serialize()..addAll(<String, String>{
    'text': text,
  });
}

/// The result of the [EnterText] command.
class EnterTextResult extends Result {
  /// Creates a successful result of entering the text.
  const EnterTextResult();

  /// Deserializes the result from JSON.
  static EnterTextResult fromJson(Map<String, dynamic> json) {
    return const EnterTextResult();
  }

  @override
  Map<String, dynamic> toJson() => const <String, String>{};
}

/// A Flutter Driver command that enables and disables text entry emulation.
class SetTextEntryEmulation extends Command {
  /// Creates a command that enables and disables text entry emulation.
  const SetTextEntryEmulation(this.enabled, { Duration timeout }) : super(timeout: timeout);

  /// Deserializes this command from the value generated by [serialize].
  SetTextEntryEmulation.deserialize(Map<String, String> json)
    : enabled = json['enabled'] == 'true',
      super.deserialize(json);

  /// Whether text entry emulation should be enabled.
  final bool enabled;

  @override
  String get kind => 'set_text_entry_emulation';

  @override
  Map<String, String> serialize() => super.serialize()..addAll(<String, String>{
    'enabled': '$enabled',
  });
}

/// The result of the [SetTextEntryEmulation] command.
class SetTextEntryEmulationResult extends Result {
  /// Creates a successful result.
  const SetTextEntryEmulationResult();

  /// Deserializes the result from JSON.
  static SetTextEntryEmulationResult fromJson(Map<String, dynamic> json) {
    return const SetTextEntryEmulationResult();
  }

  @override
  Map<String, dynamic> toJson() => const <String, String>{};
}
