//
//  AccountDisplayNameView.swift
//  Tusker
//
//  Created by Shadowfacts on 9/7/20.
//  Copyright © 2020 Shadowfacts. All rights reserved.
//

import SwiftUI
import Pachyderm
import WebURLFoundationExtras

private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options: [])

struct AccountDisplayNameView: View {
    let account: any AccountProtocol
    let textStyle: Font.TextStyle
    @ScaledMetric var emojiSize: CGFloat
    @State var text: Text
    @State var emojiRequests = [ImageCache.Request]()
    
    init(account: any AccountProtocol, textStyle: Font.TextStyle, emojiSize: CGFloat) {
        self.account = account
        self.textStyle = textStyle
        self._emojiSize = ScaledMetric(wrappedValue: emojiSize, relativeTo: textStyle)
        let name = account.displayName.isEmpty ? account.username : account.displayName
        self._text = State(initialValue: Text(verbatim: name))
    }
    
    var body: some View {
        text
            .font(.system(textStyle).weight(.semibold))
            .onAppear(perform: self.loadEmojis)
    }
    
    private func loadEmojis() {
        let fullRange = NSRange(account.displayName.startIndex..., in: account.displayName)
        let matches = emojiRegex.matches(in: account.displayName, options: [], range: fullRange)
        guard !matches.isEmpty else { return }
        
        let emojiSize = self.emojiSize
        let emojiImages = MultiThreadDictionary<String, Image>()
        
        let group = DispatchGroup()
        
        for emoji in account.emojis {
            guard matches.contains(where: { (match) in
                let matchShortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
                return emoji.shortcode == matchShortcode
            }) else {
                continue
            }
            
            group.enter()
            let request = ImageCache.emojis.get(URL(emoji.url)!) { (_, image) in
                defer { group.leave() }
                guard let image = image else { return }
                
                let size = CGSize(width: emojiSize, height: emojiSize)
                let renderer = UIGraphicsImageRenderer(size: size)
                let resized = renderer.image { (ctx) in
                    image.draw(in: CGRect(origin: .zero, size: size))
                }
                
                emojiImages[emoji.shortcode] = Image(uiImage: resized)
            }
            if let request = request {
                emojiRequests.append(request)
            }
        }
        
        group.notify(queue: .main) {
            var text: Text?
            
            var endIndex = account.displayName.utf16.count
            
            // iterate backwards as to not alter the indices of earlier matches
            for match in matches.reversed() {
                let shortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
                guard let image = emojiImages[shortcode] else { continue }
                
                let afterCurrentMatch = (account.displayName as NSString).substring(with: NSRange(location: match.range.upperBound, length: endIndex - match.range.upperBound))
                
                if let subsequent = text {
                    text = Text(image) + Text(verbatim: afterCurrentMatch) + subsequent
                } else {
                    text = Text(image) + Text(verbatim: afterCurrentMatch)
                }
                
                endIndex = match.range.lowerBound
            }
            
            let beforeLastMatch = (account.displayName as NSString).substring(to: endIndex)
            
            if let text = text {
                self.text = Text(verbatim: beforeLastMatch) + text
            } else {
                self.text = Text(verbatim: beforeLastMatch)
            }
        }
    }
}

//struct AccountDisplayNameLabel_Previews: PreviewProvider {
//    static var previews: some View {
//        AccountDisplayNameView()
//    }
//}
