//
//  GMTextAroundV2Label.swift
//  Gengmei
//
//  Created by lizhen on 2018/8/22.
//  Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//

import UIKit
import SnapKit
import GMFoundation

// 使用exclusionRect随便指定要排除的区域
// 使用exclusionView指定需要在排除区域显示的内容，该view可以随便自定义
// 注意exclusionRect的y坐标，y坐标偏上时会导致上一行内容不能显示，并且立即停止绘制
@objcMembers
class GMExclusionLabel: UILabel {
    // MARK: - 私有属性
    private let textContainer = NSTextContainer()
    private let layoutManager = NSLayoutManager()
    private let textStorage = NSTextStorage()

    // MARK: - public 属性
    private(set) var exclusionRect: CGRect = CGRect.zero
    private(set) var exclusionView: UIView!
    var contentSize = CGSize.zero {
        didSet {
            textContainer.size = contentSize
        }
    }

    /// 使用该属性控制排除区域是否显示
    var isExclusionViewHidden: Bool = true {
        didSet {
            exclusionView?.isHidden = isExclusionViewHidden
            textContainer.exclusionPaths = isExclusionViewHidden ? [] : [UIBezierPath(rect: exclusionRect)]
        }
    }

    override var lineBreakMode: NSLineBreakMode {
        didSet {
            textContainer.lineBreakMode = lineBreakMode
        }
    }
    
    override var numberOfLines: Int {
        didSet {
            textContainer.maximumNumberOfLines = numberOfLines
        }
    }

    /// 使用attributedContent而非UILabel.text或者UILabel.attribtedText绘制文字
    var attributedContent: NSAttributedString? {
        didSet {
            if attributedContent != nil {
                textStorage.setAttributedString(attributedContent!)
                invalidateIntrinsicContentSize()
                setNeedsDisplay()
            }
        }
    }

    // MARK: - Public 方法
    /// 添加排除区域
    ///
    /// - Parameters:
    ///   - exclusionRect: 待排除的区域
    ///   - view: 需要在排除区域显示的view
    @objc(initWithExclusionRect:innerView:)
    convenience init(with exclusionRect: CGRect, innerView view: UIView) {
        self.init()

        self.exclusionRect = exclusionRect
        textContainer.exclusionPaths = [UIBezierPath(rect: exclusionRect)]
        exclusionView = view
        exclusionView.frame = exclusionRect
        addSubview(view)

        isUserInteractionEnabled = true
        prepareTextSystem()
    }

    // MARK: - 私有方法
    private func prepareTextSystem() {
        textContainer.lineFragmentPadding = 0
        textContainer.lineBreakMode = NSLineBreakMode.byTruncatingTail
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)
    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }

    override func drawText(in rect: CGRect) {
        if attributedContent != nil {
            textStorage.setAttributedString(attributedContent!)
        }
        let glyphRange = layoutManager.glyphRange(for: textContainer)
        layoutManager.drawBackground(forGlyphRange: glyphRange, at: CGPoint.zero)
        layoutManager.drawGlyphs(forGlyphRange: glyphRange, at: CGPoint(x: 0, y: 0))
    }
}
