@startuml
'https://plantuml.com/sequence-diagram

!theme bluegray
!pragma teoz true

skinparam backgroundColor #whitesmoke
title Reconnection Android

participant UI
participant MobileMessenger
participant MessagingClient
participant StateMachine
participant PlatformSocket
participant OkHttpWebSocket
participant ReconnectionHandler
participant MessageStore

UI -> MobileMessenger: createMessagingClient(Configuration)
MobileMessenger -> ReconnectionHandler: init(reconnectionTimeoutInSeconds)
ReconnectionHandler -> ReconnectionHandler: setMaxAttempts
MobileMessenger --> UI: MessagingClient
UI -> MessagingClient: connect
MessagingClient -> StateMachine: onConnect
StateMachine --> UI: stateChangedListener(old = Idle, new = Connecting)
MessagingClient -> PlatformSocket: connect
PlatformSocket -> OkHttpWebSocket: init

alt #aaff8833 SUCCESS
    OkHttpWebSocket --> PlatformSocket: onOpen
    PlatformSocket --> MessagingClient: onOpen
    MessagingClient -> StateMachine: onConnectionOpened
    StateMachine --> UI: stateChangedListener(old = Connecting, new = Connected)
    loop #fcfcfcaa forever
    PlatformSocket -> OkHttpWebSocket: ping (every 15 seconds)
    PlatformSocket -> PlatformSocket: waitForPong
        alt #ffaaff33 pong not received
            PlatformSocket -> OkHttpWebSocket: cancelPings
            PlatformSocket -> OkHttpWebSocket: closeSocket
            PlatformSocket -> MessagingClient: onFailure
            MessagingClient -> MessageStore: invalidateConversationCache
            MessagingClient -> ReconnectionHandler: shouldReconnect
            ReconnectionHandler --> MessagingClient: attempt > maxAttempts
            ReconnectionHandler -> ReconnectionHandler: attempt++
            alt #aaff8833 shouldReconnect == true
                MessagingClient -> StateMachine: onReconnecting
                StateMachine --> UI: stateChangedListener(old = Configured, new = Reconnecting)
                MessagingClient -> PlatformSocket: connect
                note right MessagingClient
                                In case connect failed iterate over shouldReconnect
                            end note
                PlatformSocket -> OkHttpWebSocket: init
                OkHttpWebSocket --> PlatformSocket: onOpen
                PlatformSocket --> MessagingClient: onOpen
                MessagingClient -> PlatformSocket: configure
                note right MessagingClient
                                In case configure failed iterate over shouldReconnect
                end note
                PlatformSocket -> OkHttpWebSocket: sendMessage(configureMessage)
                OkHttpWebSocket --> PlatformSocket: onMessage(configureSuccess)
                PlatformSocket --> MessagingClient: onConfigured
                MessagingClient -> ReconnectionHandler: clear
                ReconnectionHandler -> ReconnectionHandler: attempt = 0
                MessagingClient -> StateMachine: onSessionConfigured
                StateMachine --> UI: stateChangedListener(old = Reconnecting, new = Configured)
            else #ffaaff33 shouldReconnect == false
                MessagingClient -> StateMachine: onError
                StateMachine --> UI: stateChangedListener(old = Reconnecting, new = Error)
            end
        end
    OkHttpWebSocket --> PlatformSocket: pong
    end
alt SUCCESS
    MessagingClient -> PlatformSocket: configure
    PlatformSocket -> OkHttpWebSocket: sendMessage(configureMessage)
    OkHttpWebSocket --> PlatformSocket: onMessage(configureSuccess)
    PlatformSocket --> MessagingClient: onConfigured
    MessagingClient -> StateMachine: onSessionConfigured
    StateMachine --> UI: stateChangedListener(old = Connected, new = Configured)
else #ffaaff33 FAILURE
    PlatformSocket --> MessagingClient: onFailure
        note right MessagingClient
                   In case configure failed iterate over shouldReconnect
        end note
    MessagingClient --> UI: onStateChanged(Error)
end
else #ffaaff33 FAILURE
    PlatformSocket --> MessagingClient: onFailure
     note right MessagingClient
                       In case connect failed iterate over shouldReconnect
            end note
    MessagingClient --> UI: onStateChanged(Error)
end
@enduml
