# Input Utils - Documentation d'Implémentation

## Vue d'Ensemble

Le module `input_utils.py` fournit une interface complète pour exécuter des actions UI (souris, clavier) avec support du rollback et journalisation complète.

## Fonctionnalités Implémentées

### 1. Classe ActionType (Enum)

Énumération des types d'actions supportées :
- ✅ `CLICK` - Clics souris
- ✅ `TYPE` - Saisie texte
- ✅ `SCROLL` - Défilement
- ✅ `WAIT` - Attente temporisée
- ✅ `MOVE` - Déplacement souris
- ✅ `DRAG` - Glisser-déposer

### 2. Classe InputUtils

#### Initialisation
- ✅ Configuration PyAutoGUI avec FAILSAFE activé
- ✅ Pause configurable entre actions
- ✅ Historique des actions pour rollback
- ✅ Mapping AZERTY pour caractères spéciaux
- ✅ Intégration avec Logger pour traçabilité

#### Méthodes d'Action

##### `click(x, y, button="left", clicks=1, interval=0.0)`
- ✅ Effectue un clic souris à la position spécifiée
- ✅ Support multi-boutons (left, right, middle)
- ✅ Support clics multiples (double-clic, etc.)
- ✅ Enregistre la position précédente pour rollback
- ✅ Logging complet de l'opération

##### `type_text(text, interval=0.0, use_azerty=True)`
- ✅ Saisit du texte au clavier
- ✅ Support du mapping AZERTY
- ✅ Intervalle configurable entre caractères
- ✅ Enregistre la longueur pour rollback (suppression)
- ✅ Logging du texte saisi

##### `scroll(direction, amount=3, x=None, y=None)`
- ✅ Effectue un défilement vertical ou horizontal
- ✅ Directions supportées : up, down, left, right
- ✅ Quantité configurable
- ✅ Position optionnelle
- ✅ Action inversible pour rollback

##### `wait(duration)`
- ✅ Attend pendant une durée spécifiée
- ✅ Enregistré dans l'historique
- ✅ Non inversible (pas de rollback)

##### `move(x, y, duration=0.2)`
- ✅ Déplace la souris vers une position
- ✅ Durée de mouvement configurable
- ✅ Enregistre la position précédente
- ✅ Inversible pour rollback

##### `drag(start_x, start_y, end_x, end_y, duration=0.5, button="left")`
- ✅ Effectue un glisser-déposer
- ✅ Support multi-boutons
- ✅ Durée configurable
- ✅ Complètement inversible

#### Méthodes de Rollback

##### `get_inverse_action(action)`
- ✅ Génère l'action inverse pour rollback
- ✅ Support pour tous les types d'actions inversibles
- ✅ Retourne None pour actions non inversibles

**Actions inversibles :**
- `CLICK` → Retour à la position précédente
- `TYPE` → Suppression du texte (backspace × longueur)
- `SCROLL` → Défilement inverse
- `MOVE` → Retour à la position précédente
- `DRAG` → Glissement inverse

**Actions non inversibles :**
- `WAIT` → Pas d'inverse logique

##### `execute_inverse_action(action)`
- ✅ Exécute l'action inverse générée
- ✅ Gestion d'erreurs robuste
- ✅ Retourne True/False selon le succès

#### Méthode d'Exécution Unifiée

##### `execute_action(action_data)`
- ✅ Exécute une action depuis un dictionnaire
- ✅ Calcul automatique du centre de bbox
- ✅ Support de tous les types d'actions
- ✅ Interface unifiée pour l'orchestrateur

**Format d'entrée :**
```python
action_data = {
    "action_type": "click",  # ou "type", "scroll", etc.
    "bbox": (x, y, w, h),    # Bounding box de l'élément
    "parameters": {          # Paramètres spécifiques
        "button": "left",
        "text": "...",
        "direction": "down",
        # etc.
    }
}
```

**Actions supportées :**
- `click` - Clic simple
- `double_click` - Double-clic
- `right_click` - Clic droit
- `type` - Saisie texte
- `scroll` - Défilement
- `wait` - Attente
- `move` - Déplacement
- `drag` - Glisser-déposer

#### Méthodes Utilitaires

##### `get_action_history(limit=50)`
- ✅ Retourne l'historique des actions
- ✅ Limite configurable
- ✅ Utilisé pour rollback et analyse

##### `clear_history()`
- ✅ Efface l'historique des actions
- ✅ Logging de l'opération

##### `_convert_to_azerty(text)` (privée)
- ✅ Convertit du texte pour clavier AZERTY
- ✅ Mapping des caractères spéciaux
- ✅ PyAutoGUI gère déjà le layout système

## Conformité aux Exigences

### Exigence 3.2
> LORSQUE le Système_RPA fonctionne en Mode_Autopilot, LE Système_RPA DOIT exécuter automatiquement les actions suggérées

✅ **Implémenté** : La méthode `execute_action()` permet l'exécution automatique depuis l'orchestrateur.

### Exigence 3.4
> LORSQU'une action automatisée échoue, LE Système_RPA DOIT effectuer un rollback des 3 dernières actions

✅ **Implémenté** : 
- `get_inverse_action()` génère les actions inverses
- `execute_inverse_action()` exécute le rollback
- `action_history` conserve toutes les actions

### Exigence 3.5
> LORSQU'un rollback est effectué, LE Système_RPA DOIT journaliser l'événement

✅ **Implémenté** : Toutes les actions et leurs inverses sont loggées via `self.logger.log_action()`.

### Exigence 5.1
> LE Système_RPA DOIT supporter les claviers AZERTY

✅ **Implémenté** : 
- Mapping AZERTY dans `azerty_mapping`
- Méthode `_convert_to_azerty()`
- Option `use_azerty` dans `type_text()`

## Sécurité

### FAILSAFE
- ✅ `pyautogui.FAILSAFE = True` activé
- ✅ Déplacer la souris dans un coin arrête toutes les opérations
- ✅ Protection contre les boucles infinies

### Pause entre Actions
- ✅ Configurable via `config["input"]["pause_between_actions"]`
- ✅ Évite les actions trop rapides
- ✅ Améliore la fiabilité

### Journalisation Complète
- ✅ Toutes les actions loggées avec paramètres complets
- ✅ Positions précédentes enregistrées
- ✅ Timestamps pour traçabilité
- ✅ Erreurs capturées et loggées

## Format de l'Historique

Chaque action dans `action_history` contient :

```python
{
    "type": "click",              # Type d'action
    "x": 450,                     # Coordonnées
    "y": 320,
    "button": "left",             # Paramètres spécifiques
    "clicks": 1,
    "previous_position": (100, 200),  # Pour rollback
    "timestamp": 1234567890.123   # Horodatage
}
```

## Utilisation

### Exemple Basique

```python
from geniusia2.core.utils.input_utils import InputUtils
from geniusia2.core.logger import Logger
from geniusia2.core.config import get_config

# Initialiser
logger = Logger()
config = get_config()
input_utils = InputUtils(logger, config)

# Effectuer un clic
success = input_utils.click(450, 320, button="left")

# Saisir du texte
success = input_utils.type_text("Bonjour!", use_azerty=True)

# Défiler
success = input_utils.scroll("down", amount=3)

# Obtenir l'historique
history = input_utils.get_action_history(limit=10)
```

### Exemple avec Rollback

```python
# Exécuter plusieurs actions
input_utils.click(100, 100)
input_utils.type_text("test")
input_utils.click(200, 200)

# Obtenir les 3 dernières actions
recent_actions = input_utils.get_action_history(limit=3)

# Rollback dans l'ordre inverse
for action in reversed(recent_actions):
    input_utils.execute_inverse_action(action)
```

### Exemple avec l'Orchestrateur

```python
# L'orchestrateur prépare l'action
action_data = {
    "action_type": "click",
    "bbox": (450, 320, 120, 40),
    "parameters": {"button": "left"}
}

# Exécution unifiée
success = input_utils.execute_action(action_data)

if not success:
    # Rollback des 3 dernières actions
    recent = input_utils.get_action_history(limit=3)
    for action in reversed(recent):
        input_utils.execute_inverse_action(action)
```

## Intégration avec l'Orchestrateur

L'orchestrateur utilise `InputUtils` dans sa méthode `execute_action()` :

```python
# Dans orchestrator.py
def execute_action(self, decision: Dict[str, Any]):
    action = decision.get("action")
    
    # Préparer les données d'action
    action_data = {
        "action_type": action.action_type,
        "bbox": action.bbox,
        "parameters": action.parameters
    }
    
    # Exécuter via InputUtils
    success = self.input_utils.execute_action(action_data)
    
    if not success:
        # Rollback si échec
        self.rollback_last_actions(count=3)
```

## Dépendances

### Requises
- `pyautogui` - Contrôle souris et clavier
- `time` - Gestion des délais
- `typing` - Annotations de types
- `enum` - Énumération des types d'actions

### Internes
- `Logger` - Journalisation chiffrée
- `config` - Configuration globale

## Tests

Tests de validation dans `test_input_utils_simple.py` :
- ✅ Vérification de la structure
- ✅ Présence de toutes les méthodes
- ✅ Support AZERTY
- ✅ Support rollback
- ✅ Sécurité (FAILSAFE, logging)
- ✅ Conformité aux exigences

## Notes d'Implémentation

1. **PyAutoGUI** : Utilisé pour toutes les opérations bas niveau
2. **FAILSAFE** : Toujours activé pour sécurité
3. **Historique** : Conservé en mémoire, pas persisté
4. **AZERTY** : PyAutoGUI détecte automatiquement le layout système
5. **Rollback** : Limité aux actions inversibles logiquement
6. **Logging** : Toutes les opérations sont tracées

## Limitations Connues

1. **Clics non inversibles** : Un clic ne peut pas être "annulé" logiquement
2. **Attentes non inversibles** : Le temps ne peut pas être "rembobiné"
3. **Dépendance système** : Nécessite un environnement graphique
4. **Permissions** : Peut nécessiter des permissions spéciales sur certains OS

## Statut

✅ **Implémentation COMPLÈTE**

Toutes les fonctionnalités requises sont implémentées :
- ✅ Actions souris (clic, déplacement, glisser-déposer)
- ✅ Saisie texte avec support AZERTY
- ✅ Défilement vertical et horizontal
- ✅ Actions inverses pour rollback
- ✅ Historique des actions
- ✅ Logging complet
- ✅ Gestion d'erreurs robuste
- ✅ Interface unifiée pour l'orchestrateur

## Prochaines Étapes

L'InputUtils est maintenant prêt pour intégration avec :
1. **Orchestrateur** - Exécution des actions en mode Autopilot
2. **Moteur de Rejeu** - Rollback automatique en cas d'échec
3. **Tests d'intégration** - Validation avec actions réelles

## Exemple Complet

```python
#!/usr/bin/env python3
"""Exemple d'utilisation complète d'InputUtils"""

from geniusia2.core.utils.input_utils import InputUtils
from geniusia2.core.logger import Logger
from geniusia2.core.config import get_config

# Initialisation
logger = Logger()
config = get_config()
input_utils = InputUtils(logger, config)

# Scénario : Remplir un formulaire
print("Remplissage du formulaire...")

# 1. Cliquer sur le champ nom
input_utils.click(300, 200)
input_utils.wait(0.5)

# 2. Saisir le nom
input_utils.type_text("Jean Dupont")
input_utils.wait(0.3)

# 3. Cliquer sur le champ email
input_utils.click(300, 250)
input_utils.wait(0.5)

# 4. Saisir l'email
input_utils.type_text("jean.dupont@example.com")
input_utils.wait(0.3)

# 5. Défiler vers le bas
input_utils.scroll("down", amount=3)
input_utils.wait(0.5)

# 6. Cliquer sur le bouton valider
success = input_utils.click(450, 400)

if not success:
    print("Échec du clic, rollback...")
    # Rollback des 3 dernières actions
    history = input_utils.get_action_history(limit=3)
    for action in reversed(history):
        input_utils.execute_inverse_action(action)
else:
    print("Formulaire soumis avec succès!")

# Afficher l'historique
print(f"\nActions effectuées: {len(input_utils.get_action_history())}")
```
