# DO NOT EDIT THIS FILE!
#
# This file is generated from the CDP specification. If you need to make
# changes, edit the generator and regenerate all of the modules.
#
# CDP domain: Accessibility (experimental)
from __future__ import annotations
from .util import event_class, T_JSON_DICT
from dataclasses import dataclass
import enum
import typing
from . import dom
from . import runtime


class AXNodeId(str):
    '''
    Unique accessibility node identifier.
    '''
    def to_json(self) -> str:
        return self

    @classmethod
    def from_json(cls, json: str) -> AXNodeId:
        return cls(json)

    def __repr__(self):
        return 'AXNodeId({})'.format(super().__repr__())


class AXValueType(enum.Enum):
    '''
    Enum of possible property types.
    '''
    BOOLEAN = "boolean"
    TRISTATE = "tristate"
    BOOLEAN_OR_UNDEFINED = "booleanOrUndefined"
    IDREF = "idref"
    IDREF_LIST = "idrefList"
    INTEGER = "integer"
    NODE = "node"
    NODE_LIST = "nodeList"
    NUMBER = "number"
    STRING = "string"
    COMPUTED_STRING = "computedString"
    TOKEN = "token"
    TOKEN_LIST = "tokenList"
    DOM_RELATION = "domRelation"
    ROLE = "role"
    INTERNAL_ROLE = "internalRole"
    VALUE_UNDEFINED = "valueUndefined"

    def to_json(self):
        return self.value

    @classmethod
    def from_json(cls, json):
        return cls(json)


class AXValueSourceType(enum.Enum):
    '''
    Enum of possible property sources.
    '''
    ATTRIBUTE = "attribute"
    IMPLICIT = "implicit"
    STYLE = "style"
    CONTENTS = "contents"
    PLACEHOLDER = "placeholder"
    RELATED_ELEMENT = "relatedElement"

    def to_json(self):
        return self.value

    @classmethod
    def from_json(cls, json):
        return cls(json)


class AXValueNativeSourceType(enum.Enum):
    '''
    Enum of possible native property sources (as a subtype of a particular AXValueSourceType).
    '''
    FIGCAPTION = "figcaption"
    LABEL = "label"
    LABELFOR = "labelfor"
    LABELWRAPPED = "labelwrapped"
    LEGEND = "legend"
    TABLECAPTION = "tablecaption"
    TITLE = "title"
    OTHER = "other"

    def to_json(self):
        return self.value

    @classmethod
    def from_json(cls, json):
        return cls(json)


@dataclass
class AXValueSource:
    '''
    A single source for a computed AX property.
    '''
    #: What type of source this is.
    type_: AXValueSourceType

    #: The value of this property source.
    value: typing.Optional[AXValue] = None

    #: The name of the relevant attribute, if any.
    attribute: typing.Optional[str] = None

    #: The value of the relevant attribute, if any.
    attribute_value: typing.Optional[AXValue] = None

    #: Whether this source is superseded by a higher priority source.
    superseded: typing.Optional[bool] = None

    #: The native markup source for this value, e.g. a <label> element.
    native_source: typing.Optional[AXValueNativeSourceType] = None

    #: The value, such as a node or node list, of the native source.
    native_source_value: typing.Optional[AXValue] = None

    #: Whether the value for this property is invalid.
    invalid: typing.Optional[bool] = None

    #: Reason for the value being invalid, if it is.
    invalid_reason: typing.Optional[str] = None

    def to_json(self):
        json = dict()
        json['type'] = self.type_.to_json()
        if self.value is not None:
            json['value'] = self.value.to_json()
        if self.attribute is not None:
            json['attribute'] = self.attribute
        if self.attribute_value is not None:
            json['attributeValue'] = self.attribute_value.to_json()
        if self.superseded is not None:
            json['superseded'] = self.superseded
        if self.native_source is not None:
            json['nativeSource'] = self.native_source.to_json()
        if self.native_source_value is not None:
            json['nativeSourceValue'] = self.native_source_value.to_json()
        if self.invalid is not None:
            json['invalid'] = self.invalid
        if self.invalid_reason is not None:
            json['invalidReason'] = self.invalid_reason
        return json

    @classmethod
    def from_json(cls, json):
        return cls(
            type_=AXValueSourceType.from_json(json['type']),
            value=AXValue.from_json(json['value']) if 'value' in json else None,
            attribute=str(json['attribute']) if 'attribute' in json else None,
            attribute_value=AXValue.from_json(json['attributeValue']) if 'attributeValue' in json else None,
            superseded=bool(json['superseded']) if 'superseded' in json else None,
            native_source=AXValueNativeSourceType.from_json(json['nativeSource']) if 'nativeSource' in json else None,
            native_source_value=AXValue.from_json(json['nativeSourceValue']) if 'nativeSourceValue' in json else None,
            invalid=bool(json['invalid']) if 'invalid' in json else None,
            invalid_reason=str(json['invalidReason']) if 'invalidReason' in json else None,
        )


@dataclass
class AXRelatedNode:
    #: The BackendNodeId of the related DOM node.
    backend_dom_node_id: dom.BackendNodeId

    #: The IDRef value provided, if any.
    idref: typing.Optional[str] = None

    #: The text alternative of this node in the current context.
    text: typing.Optional[str] = None

    def to_json(self):
        json = dict()
        json['backendDOMNodeId'] = self.backend_dom_node_id.to_json()
        if self.idref is not None:
            json['idref'] = self.idref
        if self.text is not None:
            json['text'] = self.text
        return json

    @classmethod
    def from_json(cls, json):
        return cls(
            backend_dom_node_id=dom.BackendNodeId.from_json(json['backendDOMNodeId']),
            idref=str(json['idref']) if 'idref' in json else None,
            text=str(json['text']) if 'text' in json else None,
        )


@dataclass
class AXProperty:
    #: The name of this property.
    name: AXPropertyName

    #: The value of this property.
    value: AXValue

    def to_json(self):
        json = dict()
        json['name'] = self.name.to_json()
        json['value'] = self.value.to_json()
        return json

    @classmethod
    def from_json(cls, json):
        return cls(
            name=AXPropertyName.from_json(json['name']),
            value=AXValue.from_json(json['value']),
        )


@dataclass
class AXValue:
    '''
    A single computed AX property.
    '''
    #: The type of this value.
    type_: AXValueType

    #: The computed value of this property.
    value: typing.Optional[typing.Any] = None

    #: One or more related nodes, if applicable.
    related_nodes: typing.Optional[typing.List[AXRelatedNode]] = None

    #: The sources which contributed to the computation of this property.
    sources: typing.Optional[typing.List[AXValueSource]] = None

    def to_json(self):
        json = dict()
        json['type'] = self.type_.to_json()
        if self.value is not None:
            json['value'] = self.value
        if self.related_nodes is not None:
            json['relatedNodes'] = [i.to_json() for i in self.related_nodes]
        if self.sources is not None:
            json['sources'] = [i.to_json() for i in self.sources]
        return json

    @classmethod
    def from_json(cls, json):
        return cls(
            type_=AXValueType.from_json(json['type']),
            value=json['value'] if 'value' in json else None,
            related_nodes=[AXRelatedNode.from_json(i) for i in json['relatedNodes']] if 'relatedNodes' in json else None,
            sources=[AXValueSource.from_json(i) for i in json['sources']] if 'sources' in json else None,
        )


class AXPropertyName(enum.Enum):
    '''
    Values of AXProperty name:
    - from 'busy' to 'roledescription': states which apply to every AX node
    - from 'live' to 'root': attributes which apply to nodes in live regions
    - from 'autocomplete' to 'valuetext': attributes which apply to widgets
    - from 'checked' to 'selected': states which apply to widgets
    - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling.
    '''
    BUSY = "busy"
    DISABLED = "disabled"
    EDITABLE = "editable"
    FOCUSABLE = "focusable"
    FOCUSED = "focused"
    HIDDEN = "hidden"
    HIDDEN_ROOT = "hiddenRoot"
    INVALID = "invalid"
    KEYSHORTCUTS = "keyshortcuts"
    SETTABLE = "settable"
    ROLEDESCRIPTION = "roledescription"
    LIVE = "live"
    ATOMIC = "atomic"
    RELEVANT = "relevant"
    ROOT = "root"
    AUTOCOMPLETE = "autocomplete"
    HAS_POPUP = "hasPopup"
    LEVEL = "level"
    MULTISELECTABLE = "multiselectable"
    ORIENTATION = "orientation"
    MULTILINE = "multiline"
    READONLY = "readonly"
    REQUIRED = "required"
    VALUEMIN = "valuemin"
    VALUEMAX = "valuemax"
    VALUETEXT = "valuetext"
    CHECKED = "checked"
    EXPANDED = "expanded"
    MODAL = "modal"
    PRESSED = "pressed"
    SELECTED = "selected"
    ACTIVEDESCENDANT = "activedescendant"
    CONTROLS = "controls"
    DESCRIBEDBY = "describedby"
    DETAILS = "details"
    ERRORMESSAGE = "errormessage"
    FLOWTO = "flowto"
    LABELLEDBY = "labelledby"
    OWNS = "owns"

    def to_json(self):
        return self.value

    @classmethod
    def from_json(cls, json):
        return cls(json)


@dataclass
class AXNode:
    '''
    A node in the accessibility tree.
    '''
    #: Unique identifier for this node.
    node_id: AXNodeId

    #: Whether this node is ignored for accessibility
    ignored: bool

    #: Collection of reasons why this node is hidden.
    ignored_reasons: typing.Optional[typing.List[AXProperty]] = None

    #: This ``Node``'s role, whether explicit or implicit.
    role: typing.Optional[AXValue] = None

    #: The accessible name for this ``Node``.
    name: typing.Optional[AXValue] = None

    #: The accessible description for this ``Node``.
    description: typing.Optional[AXValue] = None

    #: The value for this ``Node``.
    value: typing.Optional[AXValue] = None

    #: All other properties
    properties: typing.Optional[typing.List[AXProperty]] = None

    #: IDs for each of this node's child nodes.
    child_ids: typing.Optional[typing.List[AXNodeId]] = None

    #: The backend ID for the associated DOM node, if any.
    backend_dom_node_id: typing.Optional[dom.BackendNodeId] = None

    def to_json(self):
        json = dict()
        json['nodeId'] = self.node_id.to_json()
        json['ignored'] = self.ignored
        if self.ignored_reasons is not None:
            json['ignoredReasons'] = [i.to_json() for i in self.ignored_reasons]
        if self.role is not None:
            json['role'] = self.role.to_json()
        if self.name is not None:
            json['name'] = self.name.to_json()
        if self.description is not None:
            json['description'] = self.description.to_json()
        if self.value is not None:
            json['value'] = self.value.to_json()
        if self.properties is not None:
            json['properties'] = [i.to_json() for i in self.properties]
        if self.child_ids is not None:
            json['childIds'] = [i.to_json() for i in self.child_ids]
        if self.backend_dom_node_id is not None:
            json['backendDOMNodeId'] = self.backend_dom_node_id.to_json()
        return json

    @classmethod
    def from_json(cls, json):
        return cls(
            node_id=AXNodeId.from_json(json['nodeId']),
            ignored=bool(json['ignored']),
            ignored_reasons=[AXProperty.from_json(i) for i in json['ignoredReasons']] if 'ignoredReasons' in json else None,
            role=AXValue.from_json(json['role']) if 'role' in json else None,
            name=AXValue.from_json(json['name']) if 'name' in json else None,
            description=AXValue.from_json(json['description']) if 'description' in json else None,
            value=AXValue.from_json(json['value']) if 'value' in json else None,
            properties=[AXProperty.from_json(i) for i in json['properties']] if 'properties' in json else None,
            child_ids=[AXNodeId.from_json(i) for i in json['childIds']] if 'childIds' in json else None,
            backend_dom_node_id=dom.BackendNodeId.from_json(json['backendDOMNodeId']) if 'backendDOMNodeId' in json else None,
        )


def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
    '''
    Disables the accessibility domain.
    '''
    cmd_dict: T_JSON_DICT = {
        'method': 'Accessibility.disable',
    }
    json = yield cmd_dict


def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
    '''
    Enables the accessibility domain which causes ``AXNodeId``'s to remain consistent between method calls.
    This turns on accessibility for the page, which can impact performance until accessibility is disabled.
    '''
    cmd_dict: T_JSON_DICT = {
        'method': 'Accessibility.enable',
    }
    json = yield cmd_dict


def get_partial_ax_tree(
        node_id: typing.Optional[dom.NodeId] = None,
        backend_node_id: typing.Optional[dom.BackendNodeId] = None,
        object_id: typing.Optional[runtime.RemoteObjectId] = None,
        fetch_relatives: typing.Optional[bool] = None
    ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[AXNode]]:
    '''
    Fetches the accessibility node and partial accessibility tree for this DOM node, if it exists.

    **EXPERIMENTAL**

    :param node_id: *(Optional)* Identifier of the node to get the partial accessibility tree for.
    :param backend_node_id: *(Optional)* Identifier of the backend node to get the partial accessibility tree for.
    :param object_id: *(Optional)* JavaScript object id of the node wrapper to get the partial accessibility tree for.
    :param fetch_relatives: *(Optional)* Whether to fetch this nodes ancestors, siblings and children. Defaults to true.
    :returns: The ``Accessibility.AXNode`` for this DOM node, if it exists, plus its ancestors, siblings and children, if requested.
    '''
    params: T_JSON_DICT = dict()
    if node_id is not None:
        params['nodeId'] = node_id.to_json()
    if backend_node_id is not None:
        params['backendNodeId'] = backend_node_id.to_json()
    if object_id is not None:
        params['objectId'] = object_id.to_json()
    if fetch_relatives is not None:
        params['fetchRelatives'] = fetch_relatives
    cmd_dict: T_JSON_DICT = {
        'method': 'Accessibility.getPartialAXTree',
        'params': params,
    }
    json = yield cmd_dict
    return [AXNode.from_json(i) for i in json['nodes']]


def get_full_ax_tree() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[AXNode]]:
    '''
    Fetches the entire accessibility tree

    **EXPERIMENTAL**

    :returns: 
    '''
    cmd_dict: T_JSON_DICT = {
        'method': 'Accessibility.getFullAXTree',
    }
    json = yield cmd_dict
    return [AXNode.from_json(i) for i in json['nodes']]
