import SwiftUI
import FoundationModels
import Observation

@Observable class ApplicationData {
   var response: AttributedString = ""
   var prompt: String = ""

   @ObservationIgnored var session: LanguageModelSession

   static let shared: ApplicationData = ApplicationData()
   private init() {
      let instructions = "Determine the city the user is talking about, and return information about it"
      session = LanguageModelSession(instructions: instructions)
   }
   func sendPrompt() async {
      do {
         let list = ["country", "language", "attractions"]
         let properties = createProperties(list: list)
         let type = DynamicGenerationSchema(name: "CityResponse", properties: properties)
         let citySchema = try GenerationSchema(root: type, dependencies: [])

         let answer = try await session.respond(to: prompt, schema: citySchema)
         
         var message = ""
         if let city = try? answer.content.value(String.self, forProperty: "city") {
            message += "City: \(city)\n"
         }
         if let country = try? answer.content.value(String.self, forProperty: "country") {
            message += "Country: \(country)\n"
         }
         if let language = try? answer.content.value(String.self, forProperty: "language") {
            message += "Language: \(language)\n"
         }
         if let currency = try? answer.content.value(String.self, forProperty: "currency") {
            message += "Currency: \(currency)\n"
         }
         if let attractions = try? answer.content.value([String].self, forProperty: "attractions") {
            message += "Attractions: \(attractions.joined(separator: ", "))\n"
         }
         var newResponse = AttributedString("\(message)\n\n")
         newResponse.font = .system(size: 16, weight: .regular)
         response.append(newResponse)
      } catch {
         response.append(AttributedString("Error accessing the model: \(error)\n\n"))
      }
      prompt = ""
   }
   func createProperties(list: [String]) -> [DynamicGenerationSchema.Property] {
      var properties: [DynamicGenerationSchema.Property] = []
      for name in list {
         switch name {
         case "city":
            properties.append(DynamicGenerationSchema.Property(name: "city", description: "The name of the city", schema: DynamicGenerationSchema(type: String.self)))
         case "country":
            properties.append(DynamicGenerationSchema.Property(name: "country", description: "The name of the country", schema: DynamicGenerationSchema(type: String.self)))
         case "language":
            properties.append(DynamicGenerationSchema.Property(name: "language", description: "The main language spoken in the city", schema: DynamicGenerationSchema(type: String.self)))
         case "currency":
            properties.append(DynamicGenerationSchema.Property(name: "currency", description: "The currency used in the city", schema: DynamicGenerationSchema(type: String.self)))
         case "attractions":
            properties.append(DynamicGenerationSchema.Property(name: "attractions", description: "A list of attractions in the city", schema: DynamicGenerationSchema (arrayOf: DynamicGenerationSchema(type: String.self), minimumElements: 3, maximumElements: 3)))
         default:
            break
         }
      }
      return properties
   }
}