use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
use rustenium_bidi_definitions::browsing_context::types::{BrowsingContext, Locator};
use rustenium_bidi_definitions::script::types::{Handle, NodeRemoteValue, SharedId};
use rustenium_core::transport::ConnectionTransport;
use rustenium_core::BidiSession;
use crate::error::bidi::{EvaluateResultError, InputError, MouseInputError, ScreenshotError};
use crate::input::{BidiKeyboard, BidiMouse, Keyboard, Mouse, MouseClickOptions, MouseMoveOptions};
use crate::nodes::bidi::node::{BidiNode, BidiNodeScreenshotOptions};
use crate::nodes::node::Node;
use crate::nodes::NodePosition;
pub struct FirefoxNode<T: ConnectionTransport, M: Mouse + Send + Sync = BidiMouse<T>, K: Keyboard + Send + Sync = BidiKeyboard<T>> {
bidi_node: BidiNode<T>,
children: Vec<FirefoxNode<T, M, K>>,
mouse: Arc<M>,
keyboard: Arc<K>,
}
impl<T: ConnectionTransport, M: Mouse + Send + Sync + 'static, K: Keyboard + Send + Sync + 'static> FirefoxNode<T, M, K> {
pub fn from_bidi(
raw_bidi_node: NodeRemoteValue,
locator: Locator,
session: Arc<Mutex<BidiSession<T>>>,
context: BrowsingContext,
mouse: Arc<M>,
keyboard: Arc<K>,
) -> Self {
let bidi_node = BidiNode::new(raw_bidi_node, locator.clone(), session.clone(), context.clone());
let children = bidi_node.children.iter()
.map(|bidi_child| {
FirefoxNode::from_bidi(
bidi_child.get_raw_node_ref().clone(),
locator.clone(),
session.clone(),
context.clone(),
mouse.clone(),
keyboard.clone(),
)
})
.collect();
Self { bidi_node, children, mouse, keyboard }
}
pub async fn mouse_move(&mut self) -> Result<(), MouseInputError> {
self.bidi_node.mouse_move(self.mouse.as_ref(), MouseMoveOptions::default()).await
}
pub async fn mouse_move_with_options(&mut self, options: MouseMoveOptions) -> Result<(), MouseInputError> {
self.bidi_node.mouse_move(self.mouse.as_ref(), options).await
}
pub async fn mouse_click(&mut self) -> Result<(), MouseInputError> {
self.bidi_node.mouse_click(self.mouse.as_ref(), MouseClickOptions::default()).await
}
pub async fn mouse_click_with_options(&mut self, options: MouseClickOptions) -> Result<(), MouseInputError> {
self.bidi_node.mouse_click(self.mouse.as_ref(), options).await
}
}
impl<T: ConnectionTransport, M: Mouse + Send + Sync + 'static, K: Keyboard + Send + Sync + 'static> Node for FirefoxNode<T, M, K> {
#[allow(refining_impl_trait)]
fn get_children_nodes(&self) -> &Vec<FirefoxNode<T, M, K>> {
&self.children
}
fn get_bidi_locator(&self) -> &Locator {
&self.bidi_node.locator
}
async fn get_inner_text(&self) -> String {
self.bidi_node.get_inner_text().await.unwrap()
}
async fn get_text_content(&self) -> String {
self.bidi_node.get_text_content().await.unwrap()
}
async fn get_inner_html(&self) -> String {
self.bidi_node.get_inner_html().await.unwrap()
}
fn get_attribute(&self, attribute_name: &str) -> Option<serde_json::Value> {
self.bidi_node.get_attribute(attribute_name)
}
fn get_attributes(&self) -> HashMap<String, serde_json::Value> {
self.bidi_node.get_attributes()
}
async fn get_position(&mut self) -> Option<&NodePosition> {
self.bidi_node.get_position().await.unwrap_or(None)
}
fn get_context_id(&self) -> &BrowsingContext {
&self.bidi_node.context_id
}
fn get_shared_id(&self) -> Option<&SharedId> {
self.bidi_node.get_raw_node_ref().shared_id.as_ref()
}
fn get_handle(&self) -> &Option<Handle> {
&self.bidi_node.get_raw_node_ref().handle
}
fn set_position(&mut self, position: NodePosition) -> () {
self.bidi_node.position = Some(position);
}
async fn scroll_into_view(&self) -> Result<(), EvaluateResultError> {
self.bidi_node.scroll_into_view().await
}
async fn is_visible(&self) -> Result<bool, EvaluateResultError> {
self.bidi_node.is_visible().await
}
async fn delete(&self) -> Result<(), EvaluateResultError> {
self.bidi_node.delete().await
}
async fn mouse_move(&mut self) -> Result<(), MouseInputError> {
self.bidi_node.mouse_move(self.mouse.as_ref(), MouseMoveOptions::default()).await
}
async fn mouse_move_with_options(&mut self, options: MouseMoveOptions) -> Result<(), MouseInputError> {
self.bidi_node.mouse_move(self.mouse.as_ref(), options).await
}
async fn mouse_click(&mut self) -> Result<(), MouseInputError> {
self.bidi_node.mouse_click(self.mouse.as_ref(), MouseClickOptions::default()).await
}
async fn mouse_click_with_options(&mut self, options: MouseClickOptions) -> Result<(), MouseInputError> {
self.bidi_node.mouse_click(self.mouse.as_ref(), options).await
}
async fn screenshot(&self) -> Result<String, ScreenshotError> {
self.bidi_node.screenshot(BidiNodeScreenshotOptions::default()).await
}
async fn screenshot_with_options(&self, options: BidiNodeScreenshotOptions) -> Result<String, ScreenshotError> {
self.bidi_node.screenshot(options).await
}
async fn type_text(&mut self, text: String) -> Result<(), InputError> {
self.bidi_node.type_text(self.keyboard.as_ref(), text).await
}
}