//
//  DiyTextElement.swift
//  ClockWidget
//
//  Created by fff on 2024/6/28.
//

import UIKit
import ObjectMapper
import Combine

class DiyTextElement: TSBaseModel, DiyElement, ObservableObject {
    @Published var text: String?
    @Published var fontName: FontName = .PingFangSC
    @Published var textColor: String?
    @Published var alignment: NSTextAlignment = .center
    @Published var backgroundColor: String?
    var fontSize: CGFloat = 20
    var lineSpace: CGFloat = 0
    
    override func mapping(map: Map) {
        text            <- map["text"]
        fontName        <- map["fontName"]
        textColor       <- map["textColor"]
        fontSize        <- map["fontSize"]
        alignment       <- map["alignment"]
        lineSpace       <- map["lineSpace"]
        backgroundColor       <- map["backgroundColor"]
    }
    
    var elementView: DiyElementView {
        return DiyTextView(element: self)
    }
    
    var supportEditActions: EditElementAction {
        return [.click, .move, .delete, .scale];
    }
}

class DiyTextView: DiyElementBaseView {
    lazy var label = ScaleLabel()
    
    override func setupContentView() {
//        self.backgroundColor = .white.withAlphaComponent(0.5)
//        contentView.backgroundColor = .blue.withAlphaComponent(0.2)
//        label.backgroundColor = .blue.withAlphaComponent(0.2)
        label.numberOfLines = 0
        contentView.addSubview(label)
        label.snp.makeConstraints { make in
            make.top.equalTo(8)
            make.bottom.equalTo(-8)
            make.leading.equalTo(8)
            make.trailing.equalTo(-8)
            make.width.greaterThanOrEqualTo(60)
        }
        
        updateContent()
        startObserve()
    }
    
    func startObserve() {
        guard let textElement = element as? DiyTextElement else { return }
        // 监听变化更新UI
        textElement.$text.receive(on: DispatchQueue.main).sink { [weak self] newValue in
            self?.updateContent()
        }.store(in: &observers)
        textElement.$fontName.receive(on: DispatchQueue.main).sink { [weak self] newValue in
            self?.updateContent()
        }.store(in: &observers)
        textElement.$textColor.receive(on: DispatchQueue.main).sink { [weak self] newValue in
            self?.updateContent()
        }.store(in: &observers)
        textElement.$alignment.receive(on: DispatchQueue.main).sink { [weak self] newValue in
            self?.updateContent()
        }.store(in: &observers)
    }
    
    func updateContent() {
        guard let textElement = element as? DiyTextElement else { return }
        
        if textElement.lineSpace > 0 {
            let style = NSMutableParagraphStyle()
            style.lineSpacing = textElement.lineSpace
            style.alignment = textElement.alignment
            label.attributedText = NSAttributedString(string: textElement.text ?? "Add Text".localized, attributes: [
                        .foregroundColor: textElement.textColor?.uiColor ?? "#111111".uiColor,
                        .font: UIFont.font(name: textElement.fontName, size: textElement.fontSize),
                        .paragraphStyle: style])
        } else {
            label.textAlignment = textElement.alignment
            label.text = textElement.text ?? "Add Text".localized
            label.font = UIFont.font(name: textElement.fontName, size: textElement.fontSize)
            label.textColor = textElement.textColor?.uiColor ?? "#111111".uiColor
        }
        
        setNeedsDisplay()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
    }
}

public class ScaleLabel: UILabel {
    
    public override class var layerClass: AnyClass {
        return CATiledLayer.classForCoder()
    }
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        if let _layer = self.layer as? CATiledLayer {
            _layer.levelsOfDetail = 10
            _layer.levelsOfDetailBias = 10
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
