//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved.
//
// 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
//
//   https://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.
//===----------------------------------------------------------------------===//

#if os(macOS)
import Foundation

public struct LaunchPlist: Encodable {
    public enum Domain: String, Codable {
        case Aqua
        case Background
        case System
    }

    public let label: String
    public let arguments: [String]

    public let environment: [String: String]?
    public let cwd: String?
    public let username: String?
    public let groupname: String?
    public let limitLoadToSessionType: [Domain]?
    public let runAtLoad: Bool?
    public let stdin: String?
    public let stdout: String?
    public let stderr: String?
    public let disabled: Bool?
    public let program: String?
    public let keepAlive: Bool?
    public let machServices: [String: Bool]?
    public let waitForDebugger: Bool?

    enum CodingKeys: String, CodingKey {
        case label = "Label"
        case arguments = "ProgramArguments"
        case environment = "EnvironmentVariables"
        case cwd = "WorkingDirectory"
        case username = "UserName"
        case groupname = "GroupName"
        case limitLoadToSessionType = "LimitLoadToSessionType"
        case runAtLoad = "RunAtLoad"
        case stdin = "StandardInPath"
        case stdout = "StandardOutPath"
        case stderr = "StandardErrorPath"
        case disabled = "Disabled"
        case program = "Program"
        case keepAlive = "KeepAlive"
        case machServices = "MachServices"
        case waitForDebugger = "WaitForDebugger"
    }

    public init(
        label: String,
        arguments: [String],
        environment: [String: String]? = nil,
        cwd: String? = nil,
        username: String? = nil,
        groupname: String? = nil,
        limitLoadToSessionType: [Domain]? = nil,
        runAtLoad: Bool? = nil,
        stdin: String? = nil,
        stdout: String? = nil,
        stderr: String? = nil,
        disabled: Bool? = nil,
        program: String? = nil,
        keepAlive: Bool? = nil,
        machServices: [String]? = nil,
        waitForDebugger: Bool? = nil
    ) {
        self.label = label
        self.arguments = arguments
        self.environment = environment
        self.cwd = cwd
        self.username = username
        self.groupname = groupname
        self.limitLoadToSessionType = limitLoadToSessionType
        self.runAtLoad = runAtLoad
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.disabled = disabled
        self.program = program
        self.keepAlive = keepAlive
        self.waitForDebugger = waitForDebugger
        if let services = machServices {
            var machServices: [String: Bool] = [:]
            for service in services {
                machServices[service] = true
            }
            self.machServices = machServices
        } else {
            self.machServices = nil
        }
    }
}

extension LaunchPlist {
    public func encode() throws -> Data {
        let enc = PropertyListEncoder()
        enc.outputFormat = .xml
        return try enc.encode(self)
    }
}
#endif
