import Foundation
import UIKit
import BaiduMapAPI_Map

extension MapViewImpl {
    @objc public func onRichViewItemClicked(overlayId: Int, itemIndex: Int) {
        self.tappedOverlayId = overlayId
        self.tappedOverlayType = self.labelOverlays[overlayId] != nil ? "label" : "marker"
        self.tappedIsRichView = true
        self.tappedRichViewItemIndex = itemIndex
        self.overlayTapped = true
    }
    
    @objc public func addRichViewToMarker(
        _ overlayId: Int,
        _ items: [[String: Any]],
        _ config: [String: Any]
    ) -> Bool {
        guard let marker = self.markerOverlays[overlayId] else {
            return false
        }
        
        let direction = (config["direction"] as? String) ?? "vertical"
        let rootLayout: BMKBaseUIView = self.buildLayout(items, direction: direction, overlayId: overlayId)
        
        // Apply root layout properties
        // 按 BMKBaseUIView.h 设计：background(UIImage) 与 backgroundColor(UIColor) 是协同属性
        // backgroundColor 单独无效，必须配合 background 图片才会作为 tint 混合显示
        if let bg = config["background"] as? String, let img = self.loadImage(bg) {
            rootLayout.background = img
            if let bgColor = config["backgroundColor"] as? String {
                rootLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
            }
        } else if let bgColor = config["backgroundColor"] as? String {
            rootLayout.background = self.imageFromColor(UIColor.white)
            rootLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
        }
        if let gravity = config["gravity"] as? String {
            rootLayout.gravity = self.parseGravity(gravity)
        }
        
        let richView = BMKRichView()
        richView.rootView = rootLayout
        
        if let offsetX = config["offsetX"] as? Double {
            richView.offsetX = Int32(offsetX)
        }
        if let offsetY = config["offsetY"] as? Double {
            richView.offsetY = Int32(offsetY)
        }
        
        let locate = (config["locate"] as? String) ?? "bottom"
        switch locate {
        case "top": richView.locate = BMKLocateTop
        case "left": richView.locate = BMKLocateLeft
        case "right": richView.locate = BMKLocateRight
        default: richView.locate = BMKLocateBottom
        }
        
        if let priority = config["collisionPriority"] as? Int {
            richView.collisionBehavior = BMKCollisionWithAllLayersByPriority
            richView.collisionPriority = Int32(priority)
        }
        
        marker.add(richView)
        self.richViewInstances[overlayId] = richView
        self.richViewMarkerIds.insert(overlayId)
        NSLog("addRichView to marker overlayId=%d items=%d", overlayId, items.count)
        return true
    }
    
    @objc public func addRichViewToLabel(
        _ overlayId: Int,
        _ items: [[String: Any]],
        _ config: [String: Any]
    ) -> Bool {
        guard let label = self.labelOverlays[overlayId] else {
            return false
        }
        
        let direction = (config["direction"] as? String) ?? "vertical"
        let rootLayout: BMKBaseUIView = self.buildLayout(items, direction: direction, overlayId: overlayId)
        
        if let bg = config["background"] as? String, let img = self.loadImage(bg) {
            rootLayout.background = img
            if let bgColor = config["backgroundColor"] as? String {
                rootLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
            }
        } else if let bgColor = config["backgroundColor"] as? String {
            rootLayout.background = self.imageFromColor(UIColor.white)
            rootLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
        }
        if let gravity = config["gravity"] as? String {
            rootLayout.gravity = self.parseGravity(gravity)
        }
        
        let richView = BMKRichView()
        richView.rootView = rootLayout
        
        if let offsetX = config["offsetX"] as? Double {
            richView.offsetX = Int32(offsetX)
        }
        if let offsetY = config["offsetY"] as? Double {
            richView.offsetY = Int32(offsetY)
        }
        
        let locate = (config["locate"] as? String) ?? "bottom"
        switch locate {
        case "top": richView.locate = BMKLocateTop
        case "left": richView.locate = BMKLocateLeft
        case "right": richView.locate = BMKLocateRight
        default: richView.locate = BMKLocateBottom
        }
        
        if let priority = config["collisionPriority"] as? Int {
            richView.collisionBehavior = BMKCollisionWithAllLayersByPriority
            richView.collisionPriority = Int32(priority)
        }
        
        label.add(richView)
        self.richViewInstances[overlayId] = richView
        self.richViewMarkerIds.insert(overlayId)
        NSLog("addRichView to label overlayId=%d items=%d", overlayId, items.count)
        return true
    }
    
    private func buildLayout(_ items: [[String: Any]], direction: String, overlayId: Int) -> BMKBaseUIView {
        let layout: BMKBaseUIView
        if direction == "horizontal" {
            layout = BMKHorizontalLayout()
        }
        else {
            layout = BMKVerticalLayout()
        }
        
        for (index, item) in items.enumerated() {
            guard let type = item["type"] as? String else {
                continue
            }
            var view: BMKBaseUIView?
            
            if type == "text" {
                view = self.buildLabelView(item)
            }
            else if type == "image" {
                view = self.buildImageView(item)
            }
            else if type == "layout" {
                let childDir = (item["direction"] as? String) ?? "vertical"
                let children = (item["children"] as? [[String: Any]]) ?? []
                let childLayout = self.buildLayout(children, direction: childDir, overlayId: overlayId)
                if let bg = item["background"] as? String, let img = self.loadImage(bg) {
                    childLayout.background = img
                    if let bgColor = item["backgroundColor"] as? String {
                        childLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
                    }
                } else if let bgColor = item["backgroundColor"] as? String {
                    childLayout.background = self.imageFromColor(UIColor.white)
                    childLayout.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
                }
                if let gravity = item["gravity"] as? String {
                    childLayout.gravity = self.parseGravity(gravity)
                }
                view = childLayout
            }
            
            if let v = view {
                // Per-item click via setTarget:action:
                if let clickable = item["clickable"] as? Bool, clickable {
                    v.clickable = true
                    let handler = RichViewClickTarget(mapViewImpl: self, overlayId: overlayId, itemIndex: index)
                    self.richViewClickHandlers.append(handler)
                    v.setTarget(handler, action: #selector(RichViewClickTarget.handleClick))
                    if self.richViewClickTargets[overlayId] == nil {
                        self.richViewClickTargets[overlayId] = [:]
                    }
                    self.richViewClickTargets[overlayId]?[index] = v
                }
                
                if let layoutView = layout as? BMKVerticalLayout {
                    layoutView.add(v)
                }
                else if let layoutView = layout as? BMKHorizontalLayout {
                    layoutView.add(v)
                }
            }
        }
        return layout
    }
    
    private func buildLabelView(_ item: [String: Any]) -> BMKLabelUIView {
        let label = BMKLabelUIView()
        let style = BMKTextStyle()
        if let text = item["text"] as? String {
            label.text = text
        }
        if let fontSize = item["fontSize"] as? Int {
            style.fontSize = Int32(fontSize)
        }
        if let fontBold = item["fontBold"] as? Bool, fontBold {
            style.fontOption = BMKFontBold
        }
        if let fontColor = item["fontColor"] as? String {
            style.textColor = self.colorFromString(fontColor, UIColor.black)
        }
        if let borderWidth = item["borderWidth"] as? Int {
            style.borderWidth = Int32(borderWidth)
        }
        if let borderColor = item["borderColor"] as? String {
            style.borderColor = self.colorFromString(borderColor, UIColor.white)
        }
        label.style = style
        if let w = item["width"] as? Double {
            label.width = Int32(w)
        }
        if let h = item["height"] as? Double {
            label.height = Int32(h)
        }
        if let maxLines = item["maxLines"] as? Int {
            label.maxLines = Int32(maxLines)
        }
        if let bg = item["background"] as? String, let img = self.loadImage(bg) {
            label.background = img
            if let bgColor = item["backgroundColor"] as? String {
                label.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
            }
        } else if let bgColor = item["backgroundColor"] as? String {
            label.background = self.imageFromColor(UIColor.white)
            label.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
        }
        if let margin = item["margin"] as? [String: Double] {
            label.margin = self.parseMargin(margin)
        }
        if let gravity = item["gravity"] as? String {
            label.gravity = self.parseGravity(gravity)
        }
        return label
    }
    
    private func buildImageView(_ item: [String: Any]) -> BMKImageUIView {
        let imageView = BMKImageUIView()
        if let imagePath = item["image"] as? String, let img = self.loadImage(imagePath) {
            imageView.image = img
        }
        if let w = item["width"] as? Double {
            imageView.width = Int32(w)
        }
        if let h = item["height"] as? Double {
            imageView.height = Int32(h)
        }
        if let bg = item["background"] as? String, let img = self.loadImage(bg) {
            imageView.background = img
            if let bgColor = item["backgroundColor"] as? String {
                imageView.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
            }
        } else if let bgColor = item["backgroundColor"] as? String {
            imageView.background = self.imageFromColor(UIColor.white)
            imageView.backgroundColor = self.colorFromString(bgColor, UIColor.clear)
        }
        if let margin = item["margin"] as? [String: Double] {
            imageView.margin = self.parseMargin(margin)
        }
        return imageView
    }
    
    private func imageFromColor(_ color: UIColor) -> UIImage {
        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(color.cgColor)
        context.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

    private func parseMargin(_ margin: [String: Double]) -> UIEdgeInsets {
        return UIEdgeInsets(
            top: CGFloat(margin["top"] ?? 0),
            left: CGFloat(margin["left"] ?? 0),
            bottom: CGFloat(margin["bottom"] ?? 0),
            right: CGFloat(margin["right"] ?? 0)
        )
    }
    
    private func parseGravity(_ gravity: String) -> BMKGravityType {
        switch gravity {
        case "center": return BMKGravityType(rawValue: 1)
        case "right": return BMKGravityType(rawValue: 2)
        default: return BMKGravityType(rawValue: 0)
        }
    }
    
    @objc public func removeRichViewFromMarker(_ overlayId: Int) {
        guard let marker = self.markerOverlays[overlayId],
              let richView = self.richViewInstances[overlayId] else {
            return
        }
        marker.remove(richView)
        self.richViewInstances.removeValue(forKey: overlayId)
        self.richViewMarkerIds.remove(overlayId)
        self.richViewClickTargets.removeValue(forKey: overlayId)
        self.richViewClickHandlers.removeAll {
            $0.overlayId == overlayId
        }
    }
    
    @objc public func removeRichViewFromLabel(_ overlayId: Int) {
        guard let label = self.labelOverlays[overlayId],
              let richView = self.richViewInstances[overlayId] else {
            return
        }
        label.remove(richView)
        self.richViewInstances.removeValue(forKey: overlayId)
        self.richViewMarkerIds.remove(overlayId)
        self.richViewClickTargets.removeValue(forKey: overlayId)
        self.richViewClickHandlers.removeAll {
            $0.overlayId == overlayId
        }
    }
}
