' ============================================================
' WALKGUIDE — DESIGN PATTERNS (GoF)
' Flutter × Spring Boot × In-Device AI
' Pattern 5 of 7: OBSERVER (Behavioral)
' ============================================================

@startuml WalkGuide_05_Observer

skinparam monochrome false
skinparam shadowing false
skinparam defaultFontName Arial
skinparam defaultFontSize 12
skinparam roundCorner 10
skinparam ArrowColor #555555
skinparam ArrowThickness 1.2

skinparam class {
    BackgroundColor #FAFAFA
    BorderColor #AAAAAA
    HeaderBackgroundColor #E8E8E8
    FontColor #222222
    StereotypeFontColor #666666
    AttributeFontColor #333333
}

skinparam package {
    BackgroundColor #F5F5F5
    BorderColor #888888
    FontColor #333333
    FontStyle bold
}

skinparam note {
    BackgroundColor #FFFDE7
    BorderColor #F9A825
    FontColor #444444
    FontSize 11
}

' ============================================================
' PATTERN 5 — OBSERVER (Behavioral)
' ============================================================

package "⑤  Observer Pattern  [Behavioral]" #F3E5F5 {

    abstract class "Bloc<Event, State>\n<<Subject>>" as BlocSubject {
        # stateController : StreamController<State>
        + {abstract} on<E>(EventHandler)
        + add(Event event)
        + emit(State state)
        + stream : Stream<State>
    }

    class "WalkGuideBloc\n<<ConcreteSubject>>" as WalkGuideBlocObs {
        + on<StartWalkGuide>(_onStart)
        + on<StopWalkGuide>(_onStop)
        + on<CameraFrameReceived>(_onFrame)
        + on<ObstacleDetected>(_onObstacle)
        - _yoloDetector : YoloDetector
        - _ttsService : TtsService
        - _hapticService : HapticService
    }

    class "BlocBuilder<WalkGuideBloc, WalkGuideState>\n<<Observer / Widget>>" as BlocBuilderWidget {
        + builder(ctx, state) : Widget
        ' Rebuilds UI on every state emission
    }

    class "BlocListener<WalkGuideBloc, WalkGuideState>\n<<Observer / SideEffect>>" as BlocListenerWidget {
        + listener(ctx, state) : void
        ' Side effects: TTS, haptic, navigation
    }

    class "WebSocketService\n<<Subject>>" as WebSocketObs {
        - _stompClient : StompClient
        + subscribe(destination) : Stream<dynamic>
        + onLocationUpdate : StreamController
        + onSosAlert : StreamController
        + onNotification : StreamController
    }

    class "GuardianMapScreen\n<<Observer>>" as GuardianMapObs {
        + onLocationUpdate(LocationData)
        ' Updates flutter_map markers in real-time
    }

    BlocSubject <|-- WalkGuideBlocObs : extends
    WalkGuideBlocObs --> BlocBuilderWidget : emits state\n(rebuilds UI)
    WalkGuideBlocObs --> BlocListenerWidget : emits state\n(side effects)
    WebSocketObs --> GuardianMapObs : notifies\nlive location
}

note left of WebSocketObs
  Guardian subscribe topic:
  /topic/location/{userId}  — live map
  /queue/sos/{guardianId}   — SOS alert
  /queue/notif/{userId}     — notifications
  STOMP over SockJS (stomp_dart_client)
end note

@enduml
