## Pepper Abstraction Design

---

### Introduction

The Pepper robot is a complex system that can be controlled by a variety of different actions. To make the system more
manageable, we've decided implement abstraction and encapsulation in the classes related to Pepper controls.
This way, we can easily add new action events in the future. 
All these classes inherit from the `AbstractPepperActionEvent` class.

### Problems

1. The Pepper robot functions with a system that only allows one action to be executed at a time, per action category.
This means that, for example, when two speech actions are executed at the same time, the application will crash due
to a `RuntimeException` being thrown. Due to this fact, whenever the execution of multiple processes overlap,
the application will crash.

2. Besides the first problem, for the Pepper robot to be able to execute any actions, it is required to have a
QiContext available. This context is only provided in a class that extends the `RobotLifecycleCallbacks` class.
This means, that whenever the class does not extend this class, the robot will be unable to execute any actions.

### Solution

To prevent the application from crashing, we've decided to implement a queue system in the `Pepper` class.
This system allows us to queue any new actions that need to be executed whenever another action is already 
being executed. This way, we can prevent the application throwing a `RuntimeException` and thus crashing.

To tackle the second problem, we've decided to implement a system where the Pepper class has a global variable, which
holds the current QiContext. This means, that whenever a user decides to execute an action, and no current QiContext
is available, the action will be queued until a QiContext is available. This means that we can queue several actions
at once without any exceptions being thrown.

### Diagrams

#### Class Diagram

```mermaid
classDiagram
    class Pepper {
        -pepperActionEventQueue : ConcurrentLinkedQueue<AbstractPepperActionEvent>
        -isAnimating : AtomicBoolean
        -isSpeaking : AtomicBoolean
        
        +latestContext : QiContext
        +addToEventQueue(AbstractPepperActionEvent event)
        +provideQiContext(QiContext context)
        
        -processEventQueue()
    }
    class AbstractPepperActionEvent {
        +getAction()  EPepperAction
    }
    class PepperSpeechEvent {
        +phrase : String
        +locale : Locale
        +PepperSpeechEvent(String phrase, Locale locale)
        +getSay(QiContext context) Say
    }
    class PepperAnimationEvent {
        +PepperAnimationEvent(String animationName)
        +PepperAnimationEvent(String animationName, IAnimationCompletedListener listener)
        +getAnimation(QiContext context) Animate
        +animationName : String
        +IAnimationCompletedListener : IAnimationCompletedListener
    }
    Pepper <|-- AbstractPepperActionEvent
    PepperSpeechEvent <|-- AbstractPepperActionEvent
    PepperAnimationEvent <|-- AbstractPepperActionEvent
```

#### Queue System in Pepper class

```mermaid

graph LR
    subgraph "Pepper Class - Action Queue System"
        speak[say&#40String phrase&#41\nPublic\nCreate PepperSpeechEvent] --Call method--> addQueue 
        animate[animate&#40String animationName&#41\nPublic\nCreate PepperAnimationEvent] --Call method--> addQueue
        addQueue[addToEventQueue&#40AbstractPepperActionEvent event&#41\nPublic\nAdd provided event to event queue] --Add to queue--> queue[Event Queue\nPrivate\nQueue containing all events that\nneed to be executed]
        
        addQueue --Call method--> handleQueue[processEventQueue&#40&#41\nPrivate\nCheck whether there is a context\navailable, and whether an event\nis currently being executed.\nExecutes the next event in the Queue] 
        
        queue <.-> handleQueue
        
        provideCtx[provideQiContext&#40QiContext context&#41\nPublic\nSets global QiContext variable\nto provided context. If the context \nis not null,process the event queue] --Sets global QiContext variable--> handleQueue
    end
```