// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Incremental server update generated by the model in response to client
/// messages.
///
/// Content is generated as quickly as possible, and not in realtime. Clients
/// may choose to buffer and play it out in realtime.
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, *)
@available(watchOS, unavailable)
public struct LiveServerContent: Sendable {
  let serverContent: BidiGenerateContentServerContent

  /// The content that the model has generated as part of the current
  /// conversation with the user.
  ///
  /// This can be `nil` if the message signifies something else (such
  /// as the turn ending).
  public var modelTurn: ModelContent? { serverContent.modelTurn }

  /// The model has finished sending data in the current turn.
  ///
  /// Generation will only start in response to additional client messages.
  ///
  /// Can be set alongside ``modelTurn``, indicating that the content is the last in the turn.
  public var isTurnComplete: Bool { serverContent.turnComplete ?? false }

  /// The model was interrupted by a client message while generating data.
  ///
  /// If the client is playing out the content in realtime, this is a
  /// good signal to stop and empty the current queue.
  public var wasInterrupted: Bool { serverContent.interrupted ?? false }

  /// The model has finished _generating_ data for the current turn.
  ///
  /// For realtime playback, there will be a delay between when the model finishes generating
  /// content and the client has finished playing back the generated content.
  /// ``LiveServerContent/isGenerationComplete`` indicates that the model is done generating data,
  /// while ``LiveServerContent/isTurnComplete`` indicates the model is waiting for additional
  /// client messages. Sending a message during this delay may cause a
  /// ``LiveServerContent/wasInterrupted`` message to be sent.
  ///
  /// > Important: If the model ``LiveServerContent/wasInterrupted``, this will not be set. The
  /// > model will go from ``LiveServerContent/wasInterrupted`` ->
  /// > ``LiveServerContent/isTurnComplete``.
  public var isGenerationComplete: Bool { serverContent.generationComplete ?? false }

  /// Metadata specifying the sources used to ground generated content.
  public var groundingMetadata: GroundingMetadata? { serverContent.groundingMetadata }

  /// The model's interpretation of what the client said in an audio message.
  ///
  /// This field is only populated when an ``AudioTranscriptionConfig`` is provided to
  /// the `inputAudioTranscription` field in ``LiveGenerationConfig``.
  public var inputAudioTranscription: LiveAudioTranscription? {
    serverContent.inputTranscription.map { LiveAudioTranscription($0) }
  }

  /// Transcription matching the model's audio response.
  ///
  /// This field is only populated when an ``AudioTranscriptionConfig`` is provided to
  /// the  `outputAudioTranscription` field in ``LiveGenerationConfig``.
  ///
  /// > Important: Transcripts are independent to the model turn. This means transcripts may
  /// > come earlier or later than when the model sends the corresponding audio responses.
  public var outputAudioTranscription: LiveAudioTranscription? {
    serverContent.outputTranscription.map { LiveAudioTranscription($0) }
  }

  init(_ serverContent: BidiGenerateContentServerContent) {
    self.serverContent = serverContent
  }
}
