//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
import SignalCoreKit

// Every time we add a new property to TSErrorMessage, we should:
//
// * Add that property here.
// * Handle that property in the test factories.
@objc
public class TSErrorMessageBuilder: TSMessageBuilder {
    @objc
    public let errorType: TSErrorMessageType
    @objc
    public var recipientAddress: SignalServiceAddress?
    @objc
    public var senderAddress: SignalServiceAddress?
    @objc
    public var wasIdentityVerified: Bool

    public init(thread: TSThread,
                timestamp: UInt64? = nil,
                messageBody: String? = nil,
                bodyRanges: MessageBodyRanges? = nil,
                expiresInSeconds: UInt32 = 0,
                isViewOnceMessage: Bool = false,
                errorType: TSErrorMessageType,
                senderAddress: SignalServiceAddress? = nil,
                recipientAddress: SignalServiceAddress? = nil,
                wasIdentityVerified: Bool = false) {

        self.errorType = errorType
        self.senderAddress = senderAddress
        self.recipientAddress = recipientAddress
        self.wasIdentityVerified = wasIdentityVerified

        super.init(thread: thread,
                   timestamp: timestamp,
                   messageBody: messageBody,
                   bodyRanges: bodyRanges,
                   expiresInSeconds: expiresInSeconds,
                   // expireStartedAt is always initialized to zero
                   // for error messages.
                   expireStartedAt: 0,
                   isViewOnceMessage: isViewOnceMessage)
    }

    @objc
    public class func errorMessageBuilder(thread: TSThread,
                                          errorType: TSErrorMessageType) -> TSErrorMessageBuilder {
        TSErrorMessageBuilder(thread: thread, errorType: errorType)
    }

    @objc
    public class func errorMessageBuilder(errorType: TSErrorMessageType,
                                          envelope: SSKProtoEnvelope,
                                          transaction: SDSAnyWriteTransaction) -> TSErrorMessageBuilder {
        let thread = TSContactThread.getOrCreateThread(withContactAddress: envelope.sourceAddress!,
                                                       transaction: transaction)
        return TSErrorMessageBuilder(thread: thread, errorType: errorType)
    }

    @objc
    public class func errorMessageBuilder(
        errorType: TSErrorMessageType,
        sourceAci: AciObjC,
        tx: SDSAnyWriteTransaction
    ) -> TSErrorMessageBuilder {
        let thread = TSContactThread.getOrCreateThread(
            withContactAddress: SignalServiceAddress(sourceAci.wrappedAciValue),
            transaction: tx
        )
        return TSErrorMessageBuilder(thread: thread, errorType: errorType)
    }

    private var hasBuilt = false

    @objc
    public func build() -> TSErrorMessage {
        if hasBuilt {
            owsFailDebug("Don't build more than once.")
        }
        hasBuilt = true
        return TSErrorMessage(errorMessageWithBuilder: self)
    }
}

extension TSErrorMessage {

    public func plaintextBody(_ tx: SDSAnyReadTransaction) -> String {
        return self.rawBody(transaction: tx) ?? ""
    }

    @objc
    static func safetyNumberChangeDescription(for address: SignalServiceAddress?, tx: SDSAnyReadTransaction) -> String {
        guard let address else {
            // address will be nil for legacy errors
            return OWSLocalizedString(
                "ERROR_MESSAGE_NON_BLOCKING_IDENTITY_CHANGE",
                comment: "Shown when signal users safety numbers changed"
            )
        }
        let messageFormat = OWSLocalizedString(
            "ERROR_MESSAGE_NON_BLOCKING_IDENTITY_CHANGE_FORMAT",
            comment: "Shown when signal users safety numbers changed, embeds the user's {{name or phone number}}"
        )
        let recipientDisplayName = contactsManager.displayName(for: address, tx: tx).resolvedValue()
        return String(format: messageFormat, recipientDisplayName)
    }
}
