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

import SignalServiceKit
import SignalUI

public class CVComponentSenderName: CVComponentBase, CVComponent {

    public var componentKey: CVComponentKey { .senderName }

    private let state: CVComponentState.SenderName
    private var senderName: NSAttributedString { state.senderName }
    private var senderNameColor: UIColor { state.senderNameColor }

    init(itemModel: CVItemModel, senderNameState: CVComponentState.SenderName) {
        self.state = senderNameState

        super.init(itemModel: itemModel)
    }

    public func buildComponentView(componentDelegate: CVComponentDelegate) -> CVComponentView {
        CVComponentViewSenderName()
    }

    private var bodyTextColor: UIColor {
        guard let message = interaction as? TSMessage else {
            return .black
        }
        return conversationStyle.bubbleTextColor(message: message)
    }

    public func configureForRendering(componentView componentViewParam: CVComponentView,
                                      cellMeasurement: CVCellMeasurement,
                                      componentDelegate: CVComponentDelegate) {
        guard let componentView = componentViewParam as? CVComponentViewSenderName else {
            owsFailDebug("Unexpected componentView.")
            componentViewParam.reset()
            return
        }

        let outerStack = componentView.outerStack
        let innerStack = componentView.innerStack
        let label = componentView.label

        outerStack.reset()
        innerStack.reset()

        if isBorderlessWithWallpaper {
            owsAssertDebug(isIncoming)
            let backgroundView = OWSLayerView.pillView()
            backgroundView.backgroundColor = itemModel.conversationStyle.bubbleColorIncoming
            innerStack.addSubviewToFillSuperviewEdges(backgroundView)
        }

        labelConfig.applyForRendering(label: label)

        innerStack.configure(config: innerStackConfig,
                            cellMeasurement: cellMeasurement,
                            measurementKey: Self.measurementKey_innerStack,
                            subviews: [ label ])
        outerStack.configure(config: outerStackConfig,
                            cellMeasurement: cellMeasurement,
                            measurementKey: Self.measurementKey_outerStack,
                            subviews: [ innerStack ])
    }

    private var isBorderlessWithWallpaper: Bool {
        return isBorderless && conversationStyle.hasWallpaper
    }

    private var labelConfig: CVLabelConfig {
        let font = UIFont.dynamicTypeFootnote.semibold()
        return CVLabelConfig(
            text: .attributedText(senderName),
            displayConfig: .forUnstyledText(font: font, textColor: senderNameColor),
            font: font,
            textColor: senderNameColor,
            numberOfLines: 0,
            lineBreakMode: .byWordWrapping
        )
    }

    private var outerStackConfig: CVStackViewConfig {
        CVStackViewConfig(axis: .vertical,
                          alignment: .leading,
                          spacing: 0,
                          layoutMargins: .zero)
    }

    private var innerStackConfig: CVStackViewConfig {
        let layoutMargins: UIEdgeInsets = (isBorderlessWithWallpaper
                                            ? UIEdgeInsets(hMargin: 12, vMargin: 3)
                                            : .zero)
        return CVStackViewConfig(axis: .vertical,
                                 alignment: .center,
                                 spacing: 0,
                                 layoutMargins: layoutMargins)
    }

    private static let measurementKey_outerStack = "CVComponentSenderName.measurementKey_outerStack"
    private static let measurementKey_innerStack = "CVComponentSenderName.measurementKey_innerStack"

    public func measure(maxWidth: CGFloat, measurementBuilder: CVCellMeasurement.Builder) -> CGSize {
        owsAssertDebug(maxWidth > 0)

        let maxWidth = maxWidth - (outerStackConfig.layoutMargins.totalWidth +
                                    innerStackConfig.layoutMargins.totalWidth)
        let labelSize = CVText.measureLabel(config: labelConfig, maxWidth: maxWidth)
        let labelInfo = labelSize.asManualSubviewInfo
        let innerStackMeasurement = ManualStackView.measure(config: innerStackConfig,
                                                       measurementBuilder: measurementBuilder,
                                                       measurementKey: Self.measurementKey_innerStack,
                                                       subviewInfos: [ labelInfo ])
        let innerStackInfo = innerStackMeasurement.measuredSize.asManualSubviewInfo
        let outerStackMeasurement = ManualStackView.measure(config: outerStackConfig,
                                                       measurementBuilder: measurementBuilder,
                                                       measurementKey: Self.measurementKey_outerStack,
                                                       subviewInfos: [ innerStackInfo ],
                                                       maxWidth: maxWidth)
        return outerStackMeasurement.measuredSize
    }

    // MARK: -

    // Used for rendering some portion of an Conversation View item.
    // It could be the entire item or some part thereof.
    public class CVComponentViewSenderName: NSObject, CVComponentView {

        fileprivate let label = CVLabel()

        fileprivate let outerStack = ManualStackView(name: "CVComponentViewSenderName.outerStack")
        fileprivate let innerStack = ManualStackView(name: "CVComponentViewSenderName.innerStack")

        public var isDedicatedCellView = false

        public var rootView: UIView {
            outerStack
        }

        public func setIsCellVisible(_ isCellVisible: Bool) {}

        public func reset() {
            outerStack.reset()
            innerStack.reset()

            label.text = nil
        }

    }
}
