{"version":3,"file":"service-layer-facade.mjs","sources":["../../../src/lib/services/service-layer-facade.ts"],"sourcesContent":["/**\n * @file Service Layer Facade\n * @description Unified initialization and configuration for all service layer components.\n * Provides a single entry point for setting up circuit breakers, offline queue,\n * interceptors, and other enterprise patterns.\n *\n * @example\n * ```tsx\n * import { initializeServiceLayer, serviceLayer } from '@/lib/services';\n *\n * // Initialize during app bootstrap\n * await initializeServiceLayer({\n *   apiBaseUrl: 'https://api.example.com',\n *   enableOfflineQueue: true,\n *   enableCircuitBreakers: true,\n *   telemetry: {\n *     onSpan: (span) => sendToAPM(span),\n *     onMetric: (metric) => sendToMetrics(metric),\n *   },\n * });\n *\n * // Use throughout the app\n * const users = await serviceLayer.api.get('/users');\n * ```\n */\n\nimport { httpClient, type HttpClientConfig } from './http';\nimport { serviceRegistry, setupDefaultServices, type ServiceConfig } from './service-circuit-breaker';\nimport { offlineQueue, type OfflineQueueOptions } from './persistent-offline-queue';\nimport {\n  enhancedInterceptorChain,\n  createTracingInterceptors,\n  createCircuitBreakerInterceptor,\n  createTimingInterceptor,\n  createCorrelationInterceptor,\n  type CircuitBreakerConfig,\n  type TimingConfig,\n  type TraceSpan,\n} from './enhanced-interceptors';\nimport { createVersionedApi, type ApiVersion, VersioningStrategy } from './api-versioning';\nimport { globalDeduplicator } from './data-loader-batching';\nimport { globalMutationQueue } from './optimistic-mutations';\nimport { globalEventBus } from '../shared/event-utils';\nimport { networkMonitor } from '../utils/networkStatus';\n\n// =============================================================================\n// TYPE DEFINITIONS\n// =============================================================================\n\n/**\n * Telemetry configuration\n */\nexport interface TelemetryConfig {\n  /** Callback for trace spans */\n  onSpan?: (span: TraceSpan) => void;\n  /** Callback for metrics */\n  onMetric?: (metric: ServiceMetric) => void;\n  /** Callback for errors */\n  onError?: (error: ServiceError) => void;\n  /** Service name for tracing */\n  serviceName?: string;\n  /** Sampling rate (0-1) */\n  samplingRate?: number;\n}\n\n/**\n * Service metric data\n */\nexport interface ServiceMetric {\n  name: string;\n  value: number;\n  unit: string;\n  tags: Record<string, string>;\n  timestamp: number;\n}\n\n/**\n * Service error data\n */\nexport interface ServiceError {\n  message: string;\n  code: string;\n  stack?: string;\n  context: Record<string, unknown>;\n  timestamp: number;\n}\n\n/**\n * Service layer configuration\n */\nexport interface ServiceLayerConfig {\n  /** Base URL for API requests */\n  apiBaseUrl: string;\n  /** Auth service URL (if different from API) */\n  authBaseUrl?: string;\n  /** Current API version */\n  apiVersion?: ApiVersion;\n  /** Minimum supported API version */\n  minApiVersion?: ApiVersion;\n  /** API versioning strategy */\n  versioningStrategy?: VersioningStrategy;\n\n  // Feature flags\n  /** Enable offline queue (default: true) */\n  enableOfflineQueue?: boolean;\n  /** Enable circuit breakers (default: true) */\n  enableCircuitBreakers?: boolean;\n  /** Enable request deduplication (default: true) */\n  enableDeduplication?: boolean;\n  /** Enable distributed tracing (default: true) */\n  enableTracing?: boolean;\n  /** Enable request timing (default: true) */\n  enableTiming?: boolean;\n  /** Enable correlation IDs (default: true) */\n  enableCorrelation?: boolean;\n\n  // Telemetry\n  /** Telemetry configuration */\n  telemetry?: TelemetryConfig;\n\n  // Circuit breaker settings\n  /** Circuit breaker configuration */\n  circuitBreaker?: CircuitBreakerConfig;\n\n  // Offline queue settings\n  /** Offline queue configuration */\n  offlineQueue?: OfflineQueueOptions;\n\n  // Timing settings\n  /** Timing configuration */\n  timing?: TimingConfig;\n\n  // Custom services\n  /** Additional services to register */\n  services?: ServiceConfig[];\n\n  // HTTP client settings\n  /** HTTP client configuration */\n  httpClient?: HttpClientConfig;\n\n  // Event handlers\n  /** Called when service layer is initialized */\n  onInitialized?: () => void;\n  /** Called when a service becomes unhealthy */\n  onServiceUnhealthy?: (serviceName: string) => void;\n  /** Called when a service recovers */\n  onServiceRecovered?: (serviceName: string) => void;\n  /** Called when offline mode is entered */\n  onOfflineMode?: () => void;\n  /** Called when online mode is restored */\n  onOnlineMode?: () => void;\n}\n\n/**\n * Service layer status\n */\nexport interface ServiceLayerStatus {\n  initialized: boolean;\n  online: boolean;\n  services: {\n    name: string;\n    health: 'healthy' | 'degraded' | 'unhealthy' | 'unknown';\n    circuitState: 'closed' | 'open' | 'half-open';\n  }[];\n  offlineQueue: {\n    enabled: boolean;\n    pending: number;\n    processing: boolean;\n  };\n  metrics: {\n    totalRequests: number;\n    successRate: number;\n    avgResponseTime: number;\n  };\n}\n\n// =============================================================================\n// SERVICE LAYER CLASS\n// =============================================================================\n\n/**\n * Service Layer Facade\n *\n * Provides unified initialization and access to all service layer components.\n */\nclass ServiceLayerFacade {\n  private config: ServiceLayerConfig | null = null;\n  private metrics = {\n    totalRequests: 0,\n    successfulRequests: 0,\n    totalResponseTime: 0,\n  };\n  private cleanupFunctions: Array<() => void> = [];\n\n  private _initialized = false;\n\n  /**\n   * Check if service layer is initialized\n   */\n  get initialized(): boolean {\n    return this._initialized;\n  }\n\n  /**\n   * Get current configuration\n   */\n  getConfig(): ServiceLayerConfig | null {\n    return this.config;\n  }\n\n  /**\n   * Initialize the service layer\n   */\n  async initialize(config: ServiceLayerConfig): Promise<void> {\n    if (this._initialized) {\n      console.warn('[ServiceLayer] Already initialized. Call dispose() first to reinitialize.');\n      return;\n    }\n\n    this.config = {\n      // Defaults\n      apiVersion: 'v1',\n      minApiVersion: 'v1',\n      versioningStrategy: VersioningStrategy.URL_PATH,\n      enableOfflineQueue: true,\n      enableCircuitBreakers: true,\n      enableDeduplication: true,\n      enableTracing: true,\n      enableTiming: true,\n      enableCorrelation: true,\n      ...config,\n    };\n\n    try {\n      // 1. Setup circuit breakers\n      if (this.config.enableCircuitBreakers === true) {\n        this.setupCircuitBreakers();\n      }\n\n      // 2. Setup enhanced interceptors\n      this.setupInterceptors();\n\n      // 3. Initialize offline queue\n      if (this.config.enableOfflineQueue === true) {\n        await this.setupOfflineQueue();\n      }\n\n      // 4. Setup event listeners\n      this.setupEventListeners();\n\n      // 5. Setup telemetry\n      if (this.config.telemetry !== undefined) {\n        this.setupTelemetry();\n      }\n\n      this._initialized = true;\n      this.config.onInitialized?.();\n\n      console.info('[ServiceLayer] Initialized successfully', {\n        apiBaseUrl: this.config.apiBaseUrl,\n        apiVersion: this.config.apiVersion,\n        features: {\n          offlineQueue: this.config.enableOfflineQueue,\n          circuitBreakers: this.config.enableCircuitBreakers,\n          tracing: this.config.enableTracing,\n        },\n      });\n    } catch (error) {\n      console.error('[ServiceLayer] Initialization failed', error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get current service layer status\n   */\n  async getStatus(): Promise<ServiceLayerStatus> {\n    const serviceStatuses = serviceRegistry.getAllStatuses();\n    const queueStats = this.config?.enableOfflineQueue === true ? await offlineQueue.getStats() : { pending: 0 };\n\n    return {\n      initialized: this._initialized,\n      online: networkMonitor.isOnline(),\n      services: serviceStatuses.map((s) => ({\n        name: s.name,\n        health: s.health,\n        circuitState: s.circuitState,\n      })),\n      offlineQueue: {\n        enabled: this.config?.enableOfflineQueue === true,\n        pending: queueStats.pending,\n        processing: offlineQueue.isQueueProcessing(),\n      },\n      metrics: {\n        totalRequests: this.metrics.totalRequests,\n        successRate:\n          this.metrics.totalRequests > 0\n            ? this.metrics.successfulRequests / this.metrics.totalRequests\n            : 1,\n        avgResponseTime:\n          this.metrics.totalRequests > 0\n            ? this.metrics.totalResponseTime / this.metrics.totalRequests\n            : 0,\n      },\n    };\n  }\n\n  /**\n   * Get versioned API client\n   */\n  getVersionedApi(version?: ApiVersion): ReturnType<typeof createVersionedApi> {\n    if (!this.config) {\n      throw new Error('[ServiceLayer] Not initialized. Call initialize() first.');\n    }\n\n    return createVersionedApi({\n      baseUrl: this.config.apiBaseUrl,\n      currentVersion: version ?? this.config.apiVersion,\n      minimumVersion: this.config.minApiVersion,\n      strategy: this.config.versioningStrategy,\n    });\n  }\n\n  /**\n   * Reset metrics\n   */\n  resetMetrics(): void {\n    this.metrics = {\n      totalRequests: 0,\n      successfulRequests: 0,\n      totalResponseTime: 0,\n    };\n  }\n\n  /**\n   * Force process offline queue\n   */\n  async processOfflineQueue(): Promise<void> {\n    if (this.config?.enableOfflineQueue !== true) {\n      console.warn('[ServiceLayer] Offline queue is not enabled');\n      return;\n    }\n    await offlineQueue.forceProcess();\n  }\n\n  /**\n   * Reset all circuit breakers\n   */\n  resetCircuitBreakers(): void {\n    serviceRegistry.resetAll();\n  }\n\n  /**\n   * Dispose and cleanup\n   */\n  dispose(): void {\n    // Run all cleanup functions\n    for (const cleanup of this.cleanupFunctions) {\n      try {\n        cleanup();\n      } catch (error) {\n        console.error('[ServiceLayer] Cleanup error', error);\n      }\n    }\n    this.cleanupFunctions = [];\n\n    // Dispose services\n    serviceRegistry.dispose();\n    offlineQueue.dispose();\n    globalMutationQueue.destroy();\n    globalDeduplicator.clear();\n    enhancedInterceptorChain.clear();\n\n    // Reset state\n    this.config = null;\n    this._initialized = false;\n    this.resetMetrics();\n\n    console.info('[ServiceLayer] Disposed');\n  }\n\n  /**\n   * Setup circuit breakers for services\n   */\n  private setupCircuitBreakers(): void {\n    if (!this.config) return;\n\n    // Setup default API and Auth services\n    setupDefaultServices(this.config.apiBaseUrl, {\n      authBaseUrl: this.config.authBaseUrl,\n      healthCheckInterval: 60000,\n      autoStart: true,\n    });\n\n    // Register additional custom services\n    if (this.config.services !== undefined) {\n      for (const service of this.config.services) {\n        serviceRegistry.register(service);\n      }\n    }\n  }\n\n  /**\n   * Setup enhanced interceptors\n   */\n  private setupInterceptors(): void {\n    if (!this.config) return;\n\n    // Add tracing interceptors\n    if (this.config.enableTracing === true) {\n      const tracing = createTracingInterceptors({\n        serviceName: this.config.telemetry?.serviceName ?? 'frontend',\n        samplingRate: this.config.telemetry?.samplingRate ?? 1.0,\n        onSpan: this.config.telemetry?.onSpan,\n      });\n      enhancedInterceptorChain.addRequestInterceptor(tracing.request);\n      enhancedInterceptorChain.addResponseInterceptor(tracing.response);\n      enhancedInterceptorChain.addErrorInterceptor(tracing.error);\n    }\n\n    // Add correlation interceptor\n    if (this.config.enableCorrelation === true) {\n      enhancedInterceptorChain.addRequestInterceptor(createCorrelationInterceptor());\n    }\n\n    // Add circuit breaker interceptors\n    if (this.config.enableCircuitBreakers === true) {\n      const breaker = createCircuitBreakerInterceptor(this.config.circuitBreaker);\n      enhancedInterceptorChain.addRequestInterceptor(breaker.request);\n      enhancedInterceptorChain.addResponseInterceptor(breaker.response);\n      enhancedInterceptorChain.addErrorInterceptor(breaker.error);\n    }\n\n    // Add timing interceptor\n    if (this.config.enableTiming === true) {\n      enhancedInterceptorChain.addResponseInterceptor(\n        createTimingInterceptor({\n          ...this.config.timing,\n          onTiming: (data) => {\n            // Track metrics\n            this.metrics.totalRequests++;\n            this.metrics.totalResponseTime += data.duration;\n            if (data.status < 400) {\n              this.metrics.successfulRequests++;\n            }\n\n            // Emit metric\n            this.config?.telemetry?.onMetric?.({\n              name: 'http.request.duration',\n              value: data.duration,\n              unit: 'ms',\n              tags: {\n                method: data.method,\n                status: String(data.status),\n                slow: String(data.isSlow),\n              },\n              timestamp: Date.now(),\n            });\n\n            this.config?.timing?.onTiming?.(data);\n          },\n        })\n      );\n    }\n\n    // Add metrics interceptor\n    this.cleanupFunctions.push(\n      httpClient.addResponseInterceptor((response) => {\n        this.metrics.totalRequests++;\n        this.metrics.successfulRequests++;\n        return response;\n      })\n    );\n\n    this.cleanupFunctions.push(\n      httpClient.addErrorInterceptor((error) => {\n        this.metrics.totalRequests++;\n        return error;\n      })\n    );\n  }\n\n  /**\n   * Setup offline queue\n   */\n  private async setupOfflineQueue(): Promise<void> {\n    if (!this.config) return;\n\n    await offlineQueue.init();\n  }\n\n  /**\n   * Setup event listeners\n   */\n  private setupEventListeners(): void {\n    if (!this.config) return;\n\n    // Listen for service state changes\n    const unsubStateChange = globalEventBus.on('service:stateChange', (event) => {\n      if (event.to === 'open') {\n        this.config?.onServiceUnhealthy?.(event.service);\n        this.config?.telemetry?.onError?.({\n          message: `Service ${event.service} circuit opened`,\n          code: 'CIRCUIT_OPEN',\n          context: { service: event.service, health: event.health },\n          timestamp: Date.now(),\n        });\n      } else if (event.from === 'open' && event.to === 'closed') {\n        this.config?.onServiceRecovered?.(event.service);\n      }\n    });\n    this.cleanupFunctions.push(unsubStateChange);\n\n    // Listen for network status changes\n    const unsubNetwork = networkMonitor.onStatusChange((status) => {\n      if (status.online) {\n        this.config?.onOnlineMode?.();\n      } else {\n        this.config?.onOfflineMode?.();\n      }\n    });\n    this.cleanupFunctions.push(unsubNetwork);\n  }\n\n  /**\n   * Setup telemetry integration\n   */\n  private setupTelemetry(): void {\n    if (!this.config?.telemetry) return;\n\n    // Listen for offline queue events\n    const unsubEnqueued = globalEventBus.on('offlineQueue:enqueued', ({ url }) => {\n      this.config?.telemetry?.onMetric?.({\n        name: 'offline_queue.enqueued',\n        value: 1,\n        unit: 'count',\n        tags: { url },\n        timestamp: Date.now(),\n      });\n    });\n    this.cleanupFunctions.push(unsubEnqueued);\n\n    const unsubCompleted = globalEventBus.on('offlineQueue:completed', ({ url }) => {\n      this.config?.telemetry?.onMetric?.({\n        name: 'offline_queue.completed',\n        value: 1,\n        unit: 'count',\n        tags: { url },\n        timestamp: Date.now(),\n      });\n    });\n    this.cleanupFunctions.push(unsubCompleted);\n\n    const unsubFailed = globalEventBus.on('offlineQueue:failed', ({ id, url, error }) => {\n      this.config?.telemetry?.onError?.({\n        message: `Offline request failed: ${error}`,\n        code: 'OFFLINE_QUEUE_FAILED',\n        context: { id, url },\n        timestamp: Date.now(),\n      });\n    });\n    this.cleanupFunctions.push(unsubFailed);\n  }\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\n\n/**\n * Global service layer instance\n */\nexport const serviceLayer = new ServiceLayerFacade();\n\n/**\n * Initialize the service layer (convenience function)\n */\nexport async function initializeServiceLayer(config: ServiceLayerConfig): Promise<void> {\n  await serviceLayer.initialize(config);\n}\n\n/**\n * Get service layer status (convenience function)\n */\nexport async function getServiceLayerStatus(): Promise<ServiceLayerStatus> {\n  return serviceLayer.getStatus();\n}\n\n/**\n * Dispose service layer (convenience function)\n */\nexport function disposeServiceLayer(): void {\n  serviceLayer.dispose();\n}\n"],"names":["ServiceLayerFacade","config","VersioningStrategy","error","serviceStatuses","serviceRegistry","queueStats","offlineQueue","networkMonitor","s","version","createVersionedApi","cleanup","globalMutationQueue","globalDeduplicator","enhancedInterceptorChain","setupDefaultServices","service","tracing","createTracingInterceptors","createCorrelationInterceptor","breaker","createCircuitBreakerInterceptor","createTimingInterceptor","data","httpClient","response","unsubStateChange","globalEventBus","event","unsubNetwork","status","unsubEnqueued","url","unsubCompleted","unsubFailed","id","serviceLayer","initializeServiceLayer","getServiceLayerStatus","disposeServiceLayer"],"mappings":";;;;;;;;;AAyLA,MAAMA,EAAmB;AAAA,EACf,SAAoC;AAAA,EACpC,UAAU;AAAA,IAChB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,EAAA;AAAA,EAEb,mBAAsC,CAAA;AAAA,EAEtC,eAAe;AAAA;AAAA;AAAA;AAAA,EAKvB,IAAI,cAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,YAAuC;AACrC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAWC,GAA2C;AAC1D,QAAI,KAAK,cAAc;AACrB,cAAQ,KAAK,2EAA2E;AACxF;AAAA,IACF;AAEA,SAAK,SAAS;AAAA;AAAA,MAEZ,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,oBAAoBC,EAAmB;AAAA,MACvC,oBAAoB;AAAA,MACpB,uBAAuB;AAAA,MACvB,qBAAqB;AAAA,MACrB,eAAe;AAAA,MACf,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,GAAGD;AAAA,IAAA;AAGL,QAAI;AAEF,MAAI,KAAK,OAAO,0BAA0B,MACxC,KAAK,qBAAA,GAIP,KAAK,kBAAA,GAGD,KAAK,OAAO,uBAAuB,MACrC,MAAM,KAAK,kBAAA,GAIb,KAAK,oBAAA,GAGD,KAAK,OAAO,cAAc,UAC5B,KAAK,eAAA,GAGP,KAAK,eAAe,IACpB,KAAK,OAAO,gBAAA,GAEZ,QAAQ,KAAK,2CAA2C;AAAA,QACtD,YAAY,KAAK,OAAO;AAAA,QACxB,YAAY,KAAK,OAAO;AAAA,QACxB,UAAU;AAAA,UACR,cAAc,KAAK,OAAO;AAAA,UAC1B,iBAAiB,KAAK,OAAO;AAAA,UAC7B,SAAS,KAAK,OAAO;AAAA,QAAA;AAAA,MACvB,CACD;AAAA,IACH,SAASE,GAAO;AACd,oBAAQ,MAAM,wCAAwCA,CAAK,GACrDA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAyC;AAC7C,UAAMC,IAAkBC,EAAgB,eAAA,GAClCC,IAAa,KAAK,QAAQ,uBAAuB,KAAO,MAAMC,EAAa,SAAA,IAAa,EAAE,SAAS,EAAA;AAEzG,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,QAAQC,EAAe,SAAA;AAAA,MACvB,UAAUJ,EAAgB,IAAI,CAACK,OAAO;AAAA,QACpC,MAAMA,EAAE;AAAA,QACR,QAAQA,EAAE;AAAA,QACV,cAAcA,EAAE;AAAA,MAAA,EAChB;AAAA,MACF,cAAc;AAAA,QACZ,SAAS,KAAK,QAAQ,uBAAuB;AAAA,QAC7C,SAASH,EAAW;AAAA,QACpB,YAAYC,EAAa,kBAAA;AAAA,MAAkB;AAAA,MAE7C,SAAS;AAAA,QACP,eAAe,KAAK,QAAQ;AAAA,QAC5B,aACE,KAAK,QAAQ,gBAAgB,IACzB,KAAK,QAAQ,qBAAqB,KAAK,QAAQ,gBAC/C;AAAA,QACN,iBACE,KAAK,QAAQ,gBAAgB,IACzB,KAAK,QAAQ,oBAAoB,KAAK,QAAQ,gBAC9C;AAAA,MAAA;AAAA,IACR;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgBG,GAA6D;AAC3E,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,0DAA0D;AAG5E,WAAOC,EAAmB;AAAA,MACxB,SAAS,KAAK,OAAO;AAAA,MACrB,gBAAgBD,KAAW,KAAK,OAAO;AAAA,MACvC,gBAAgB,KAAK,OAAO;AAAA,MAC5B,UAAU,KAAK,OAAO;AAAA,IAAA,CACvB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,SAAK,UAAU;AAAA,MACb,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,IAAA;AAAA,EAEvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAqC;AACzC,QAAI,KAAK,QAAQ,uBAAuB,IAAM;AAC5C,cAAQ,KAAK,6CAA6C;AAC1D;AAAA,IACF;AACA,UAAMH,EAAa,aAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA6B;AAC3B,IAAAF,EAAgB,SAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AAEd,eAAWO,KAAW,KAAK;AACzB,UAAI;AACF,QAAAA,EAAA;AAAA,MACF,SAAST,GAAO;AACd,gBAAQ,MAAM,gCAAgCA,CAAK;AAAA,MACrD;AAEF,SAAK,mBAAmB,CAAA,GAGxBE,EAAgB,QAAA,GAChBE,EAAa,QAAA,GACbM,EAAoB,QAAA,GACpBC,EAAmB,MAAA,GACnBC,EAAyB,MAAA,GAGzB,KAAK,SAAS,MACd,KAAK,eAAe,IACpB,KAAK,aAAA,GAEL,QAAQ,KAAK,yBAAyB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,QAAK,KAAK,WAGVC,EAAqB,KAAK,OAAO,YAAY;AAAA,MAC3C,aAAa,KAAK,OAAO;AAAA,MACzB,qBAAqB;AAAA,MACrB,WAAW;AAAA,IAAA,CACZ,GAGG,KAAK,OAAO,aAAa;AAC3B,iBAAWC,KAAW,KAAK,OAAO;AAChC,QAAAZ,EAAgB,SAASY,CAAO;AAAA,EAGtC;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AAChC,QAAK,KAAK,QAGV;AAAA,UAAI,KAAK,OAAO,kBAAkB,IAAM;AACtC,cAAMC,IAAUC,EAA0B;AAAA,UACxC,aAAa,KAAK,OAAO,WAAW,eAAe;AAAA,UACnD,cAAc,KAAK,OAAO,WAAW,gBAAgB;AAAA,UACrD,QAAQ,KAAK,OAAO,WAAW;AAAA,QAAA,CAChC;AACD,QAAAJ,EAAyB,sBAAsBG,EAAQ,OAAO,GAC9DH,EAAyB,uBAAuBG,EAAQ,QAAQ,GAChEH,EAAyB,oBAAoBG,EAAQ,KAAK;AAAA,MAC5D;AAQA,UALI,KAAK,OAAO,sBAAsB,MACpCH,EAAyB,sBAAsBK,GAA8B,GAI3E,KAAK,OAAO,0BAA0B,IAAM;AAC9C,cAAMC,IAAUC,EAAgC,KAAK,OAAO,cAAc;AAC1E,QAAAP,EAAyB,sBAAsBM,EAAQ,OAAO,GAC9DN,EAAyB,uBAAuBM,EAAQ,QAAQ,GAChEN,EAAyB,oBAAoBM,EAAQ,KAAK;AAAA,MAC5D;AAGA,MAAI,KAAK,OAAO,iBAAiB,MAC/BN,EAAyB;AAAA,QACvBQ,EAAwB;AAAA,UACtB,GAAG,KAAK,OAAO;AAAA,UACf,UAAU,CAACC,MAAS;AAElB,iBAAK,QAAQ,iBACb,KAAK,QAAQ,qBAAqBA,EAAK,UACnCA,EAAK,SAAS,OAChB,KAAK,QAAQ,sBAIf,KAAK,QAAQ,WAAW,WAAW;AAAA,cACjC,MAAM;AAAA,cACN,OAAOA,EAAK;AAAA,cACZ,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,QAAQA,EAAK;AAAA,gBACb,QAAQ,OAAOA,EAAK,MAAM;AAAA,gBAC1B,MAAM,OAAOA,EAAK,MAAM;AAAA,cAAA;AAAA,cAE1B,WAAW,KAAK,IAAA;AAAA,YAAI,CACrB,GAED,KAAK,QAAQ,QAAQ,WAAWA,CAAI;AAAA,UACtC;AAAA,QAAA,CACD;AAAA,MAAA,GAKL,KAAK,iBAAiB;AAAA,QACpBC,EAAW,uBAAuB,CAACC,OACjC,KAAK,QAAQ,iBACb,KAAK,QAAQ,sBACNA,EACR;AAAA,MAAA,GAGH,KAAK,iBAAiB;AAAA,QACpBD,EAAW,oBAAoB,CAACtB,OAC9B,KAAK,QAAQ,iBACNA,EACR;AAAA,MAAA;AAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAmC;AAC/C,IAAK,KAAK,UAEV,MAAMI,EAAa,KAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAClC,QAAI,CAAC,KAAK,OAAQ;AAGlB,UAAMoB,IAAmBC,EAAe,GAAG,uBAAuB,CAACC,MAAU;AAC3E,MAAIA,EAAM,OAAO,UACf,KAAK,QAAQ,qBAAqBA,EAAM,OAAO,GAC/C,KAAK,QAAQ,WAAW,UAAU;AAAA,QAChC,SAAS,WAAWA,EAAM,OAAO;AAAA,QACjC,MAAM;AAAA,QACN,SAAS,EAAE,SAASA,EAAM,SAAS,QAAQA,EAAM,OAAA;AAAA,QACjD,WAAW,KAAK,IAAA;AAAA,MAAI,CACrB,KACQA,EAAM,SAAS,UAAUA,EAAM,OAAO,YAC/C,KAAK,QAAQ,qBAAqBA,EAAM,OAAO;AAAA,IAEnD,CAAC;AACD,SAAK,iBAAiB,KAAKF,CAAgB;AAG3C,UAAMG,IAAetB,EAAe,eAAe,CAACuB,MAAW;AAC7D,MAAIA,EAAO,SACT,KAAK,QAAQ,eAAA,IAEb,KAAK,QAAQ,gBAAA;AAAA,IAEjB,CAAC;AACD,SAAK,iBAAiB,KAAKD,CAAY;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,QAAQ,UAAW;AAG7B,UAAME,IAAgBJ,EAAe,GAAG,yBAAyB,CAAC,EAAE,KAAAK,QAAU;AAC5E,WAAK,QAAQ,WAAW,WAAW;AAAA,QACjC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,MAAM,EAAE,KAAAA,EAAA;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,MAAI,CACrB;AAAA,IACH,CAAC;AACD,SAAK,iBAAiB,KAAKD,CAAa;AAExC,UAAME,IAAiBN,EAAe,GAAG,0BAA0B,CAAC,EAAE,KAAAK,QAAU;AAC9E,WAAK,QAAQ,WAAW,WAAW;AAAA,QACjC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,MAAM,EAAE,KAAAA,EAAA;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,MAAI,CACrB;AAAA,IACH,CAAC;AACD,SAAK,iBAAiB,KAAKC,CAAc;AAEzC,UAAMC,IAAcP,EAAe,GAAG,uBAAuB,CAAC,EAAE,IAAAQ,GAAI,KAAAH,GAAK,OAAA9B,QAAY;AACnF,WAAK,QAAQ,WAAW,UAAU;AAAA,QAChC,SAAS,2BAA2BA,CAAK;AAAA,QACzC,MAAM;AAAA,QACN,SAAS,EAAE,IAAAiC,GAAI,KAAAH,EAAA;AAAA,QACf,WAAW,KAAK,IAAA;AAAA,MAAI,CACrB;AAAA,IACH,CAAC;AACD,SAAK,iBAAiB,KAAKE,CAAW;AAAA,EACxC;AACF;AASO,MAAME,IAAe,IAAIrC,EAAA;AAKhC,eAAsBsC,EAAuBrC,GAA2C;AACtF,QAAMoC,EAAa,WAAWpC,CAAM;AACtC;AAKA,eAAsBsC,IAAqD;AACzE,SAAOF,EAAa,UAAA;AACtB;AAKO,SAASG,IAA4B;AAC1C,EAAAH,EAAa,QAAA;AACf;"}