import Foundation

public enum EditorRenderReason: String, Hashable, Codable, Sendable {
    case initial
    case sourceChange
    case activeLineChange
    case viewUpdate
}

public struct EditorRenderPassMetric: Hashable, Sendable {
    public var reason: EditorRenderReason
    public var durationMilliseconds: Double
    public var characterCount: Int
    public var lineCount: Int
    public var activeLineIndex: Int

    public init(
        reason: EditorRenderReason,
        durationMilliseconds: Double,
        characterCount: Int,
        lineCount: Int,
        activeLineIndex: Int
    ) {
        self.reason = reason
        self.durationMilliseconds = durationMilliseconds
        self.characterCount = characterCount
        self.lineCount = lineCount
        self.activeLineIndex = activeLineIndex
    }
}

public struct EditorInstrumentationSnapshot: Hashable, Sendable {
    public var sourceChangeCount: Int
    public var selectionChangeCount: Int
    public var activeLineChangeCount: Int
    public var renderPassCount: Int
    public var totalRenderDurationMilliseconds: Double
    public var lastRenderDurationMilliseconds: Double
    public var lastRenderCharacterCount: Int
    public var lastRenderLineCount: Int
    public var lastRenderReason: EditorRenderReason?

    public init(
        sourceChangeCount: Int = 0,
        selectionChangeCount: Int = 0,
        activeLineChangeCount: Int = 0,
        renderPassCount: Int = 0,
        totalRenderDurationMilliseconds: Double = 0,
        lastRenderDurationMilliseconds: Double = 0,
        lastRenderCharacterCount: Int = 0,
        lastRenderLineCount: Int = 0,
        lastRenderReason: EditorRenderReason? = nil
    ) {
        self.sourceChangeCount = sourceChangeCount
        self.selectionChangeCount = selectionChangeCount
        self.activeLineChangeCount = activeLineChangeCount
        self.renderPassCount = renderPassCount
        self.totalRenderDurationMilliseconds = totalRenderDurationMilliseconds
        self.lastRenderDurationMilliseconds = lastRenderDurationMilliseconds
        self.lastRenderCharacterCount = lastRenderCharacterCount
        self.lastRenderLineCount = lastRenderLineCount
        self.lastRenderReason = lastRenderReason
    }

    public var averageRenderDurationMilliseconds: Double {
        guard renderPassCount > 0 else { return 0 }
        return totalRenderDurationMilliseconds / Double(renderPassCount)
    }

    public mutating func recordSourceChange() {
        sourceChangeCount += 1
    }

    public mutating func recordSelectionChange() {
        selectionChangeCount += 1
    }

    public mutating func recordActiveLineChange() {
        activeLineChangeCount += 1
    }

    public mutating func recordRenderPass(_ metric: EditorRenderPassMetric) {
        renderPassCount += 1
        totalRenderDurationMilliseconds += metric.durationMilliseconds
        lastRenderDurationMilliseconds = metric.durationMilliseconds
        lastRenderCharacterCount = metric.characterCount
        lastRenderLineCount = metric.lineCount
        lastRenderReason = metric.reason
    }
}
