# 10. Behavioral: State va Chain of Responsibility

> "Agar siz audio pleer yoki buyurtma holatini boshqarish uchun bitta ViewModel ichida 30 ta `if (isPlaying && !isPaused && hasConnection)` shartlarini yozayotgan bo'lsangiz — siz portlovchi minalar maydonida yurasiz. State patterni bu holatlarni sof matematik Holat Mashinasiga (FSM) aylantiradi."

---

## 1. State Pattern: Chekli Holat Mashinasi (FSM)

**State (Holat)** — bu obyektning ichki holati o'zgarganda, uning tashqi xatti-harakati va metodlarining reaksiyasi butunlay boshqacha bo'lishiga imkon beruvchi pattern. Obyekt go'yo o'z sinfini o'zgartirgandek taassurot qoldiradi.

```mermaid
stateDiagram-v2
    direction LR
    [*] --> Idle: Ilova ochildi
    Idle --> Buffering: play() chaqirildi
    Buffering --> Playing: Buffer to'ldi
    Playing --> Paused: pause() bosildi
    Paused --> Playing: play() bosildi
    Playing --> Failed: Tarmoq uzildi
    Failed --> Idle: retry() yoki stop()
```

---

## 2. Real Swift 6 Kodi: Audio Player Holat Mashinasi

Har bir holat alohida sinfga chiqariladi:

```swift
import Foundation

// 1. Holat Protokoli
public protocol AudioPlayerState: Sendable {
    func play(context: AudioPlayerContext)
    func pause(context: AudioPlayerContext)
    func stop(context: AudioPlayerContext)
}

// 2. Kontekst (Pleyerning o'zi)
@MainActor
public final class AudioPlayerContext {
    private var state: any AudioPlayerState
    
    public init() {
        self.state = IdleState()
    }
    
    public func setState(_ newState: any AudioPlayerState) {
        print("🔄 [State O'tishi] -> \(type(of: newState))")
        self.state = newState
    }
    
    public func play() { state.play(context: self) }
    public func pause() { state.pause(context: self) }
    public func stop() { state.stop(context: self) }
}

// 3. Aniq Holatlar (Concrete States)
public struct IdleState: AudioPlayerState {
    public func play(context: AudioPlayerContext) {
        print("▶️ Qo'shiq yuklanmoqda... (Buffering holatiga o'tish)")
        context.setState(BufferingState())
    }
    public func pause(context: AudioPlayerContext) {
        print("⚠️ Hozir hech narsa yangramayapti, pauza qilib bo'lmaydi.")
    }
    public func stop(context: AudioPlayerContext) {}
}

public struct BufferingState: AudioPlayerState {
    public func play(context: AudioPlayerContext) {
        print("⏳ Qo'shiq allaqachon yuklanmoqda, kuting...")
    }
    public func pause(context: AudioPlayerContext) {
        print("Yuklanish to'xtatildi.")
        context.setState(IdleState())
    }
    public func stop(context: AudioPlayerContext) {
        context.setState(IdleState())
    }
}

public struct PlayingState: AudioPlayerState {
    public func play(context: AudioPlayerContext) {
        print("Qo'shiq allaqachon ijro etilmoqda.")
    }
    public func pause(context: AudioPlayerContext) {
        print("⏸ Ijro pauza qilindi.")
        context.setState(PausedState())
    }
    public func stop(context: AudioPlayerContext) {
        print("⏹ Ijro to'xtatildi.")
        context.setState(IdleState())
    }
}

public struct PausedState: AudioPlayerState {
    public func play(context: AudioPlayerContext) {
        print("▶️ Ijro davom ettirilmoqda...")
        context.setState(PlayingState())
    }
    public func pause(context: AudioPlayerContext) {}
    public func stop(context: AudioPlayerContext) {
        context.setState(IdleState())
    }
}
```

---

## 3. Chain of Responsibility: Tarmoq Interceptorlar Quvuri

**Chain of Responsibility (Mas'uliyat Zanjiri)** — bu so'rovni bir nechta qayta ishlovchilar (Handlers) zanjiri orqali o'tkazish imkonini beruvchi pattern. Har bir halqa so'rovni o'zi tekshiradi, o'zgartiradi va keyingisiga uzatadi.

```mermaid
flowchart LR
    Request["Chiquvchi Tarmoq So'rovi"] --> H1["1. AuthTokenInterceptor\n(Bearer tokenni kiritadi)"]
    H1 --> H2["2. DeviceHeaderInterceptor\n(App Versiya, OS versiyani qo'shadi)"]
    H2 --> H3["3. NetworkLoggingInterceptor\n(cURL formatda log yozadi)"]
    H3 --> Server["Haqiqiy Serverga Chiqish"]

    style H1 fill:#181d26,stroke:#7da2ce,stroke-width:1px
    style H2 fill:#181d26,stroke:#7da2ce,stroke-width:1px
    style H3 fill:#181d26,stroke:#bef264,stroke-width:2px
```

### Swift 6 Interceptor Kodi:
```swift
import Foundation

public protocol RequestInterceptor: Sendable {
    var next: (any RequestInterceptor)? { get set }
    func intercept(request: URLRequest) async throws -> URLRequest
}

// 1. Token Qo'shuvchi Halqa
public final class AuthTokenInterceptor: RequestInterceptor {
    public var next: (any RequestInterceptor)?
    
    public func intercept(request: URLRequest) async throws -> URLRequest {
        var modified = request
        modified.addValue("Bearer sample_jwt_token", forHTTPHeaderField: "Authorization")
        
        if let next = next {
            return try await next.intercept(request: modified)
        }
        return modified
    }
}

// 2. Qurilma Ma'lumotlarini Qo'shuvchi Halqa
public final class DeviceHeadersInterceptor: RequestInterceptor {
    public var next: (any RequestInterceptor)?
    
    public func intercept(request: URLRequest) async throws -> URLRequest {
        var modified = request
        modified.addValue("iOS 18.0", forHTTPHeaderField: "X-OS-Version")
        modified.addValue("1.5.0", forHTTPHeaderField: "X-App-Version")
        
        if let next = next {
            return try await next.intercept(request: modified)
        }
        return modified
    }
}
```

---

## 4. Interaktiv Savol-Javob (Self-Check Quiz)

<details>
<summary><b>1-Savol: iOS tizimidagi 'UIResponder Chain' qaysi pattern asosida qurilgan?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
Nomidan ko'rinib turganidek, bu 100% **Chain of Responsibility** patternidir! Foydalanuvchi ekranga tekkanda (Touch Event), iOS avval eng pastdagi View'ga so'rov beradi. Agar u javob bermasa, uning ota View'si (`superview`), keyin `UIViewController`, keyin `UIWindow` va oxiri `UIApplication` gacha zanjir bo'ylab yuqoriga uzatiladi.
</details>

<details>
<summary><b>2-Savol: State patternida yangi holat qo'shish qanchalik oson?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
Juda oson (Open/Closed Principle). Mavjud kodlardagi birorta `if-else` ga tegmaysiz. Masalan, pleyerga `AdvertisementState` (reklama holati) qo'shish kerak bo'lsa, shunchaki yangi `struct AdvertisementState: AudioPlayerState` yaratiladi va kerakli o'tish nuqtasiga ulanadi.
</details>

---

## 5. Amaliy Topshiriq (Senior Challenge)

`OrderFSM` (Buyurtma Holat Mashinasi)ni quring:
* Holatlar: `CreatedState` -> `PaidState` -> `CookingState` -> `DeliveringState` -> `DeliveredState`.
* Shart: Agar buyurtma `DeliveringState` holatiga o'tgan bo'lsa, uni bekor qilib (`cancel()`) bo'lmasin (xatolik chiqsin). Faqat `CreatedState` va `PaidState` holatlaridagina bekor qilishga ruxsat berilsin!
