//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import DTCoreText
import Foundation

public extension DTHTMLElement {
    /// Sanitize the element using the given parameters.
    /// - Parameters:
    ///   - font: The default font to use when resetting the content of any unsupported tags.
    @objc func sanitize(font: UIFont) {
        if let name, !Self.allowedHTMLTags.contains(name) {
            // This is an unsupported tag.
            // Remove any attachments to fix rendering.
            textAttachment = nil
            
            // If the element has plain text content show that,
            // otherwise prevent the tag from displaying.
            if let stringContent = attributedString()?.string,
               !stringContent.isEmpty,
               let element = DTTextHTMLElement(name: nil, attributes: nil) {
                element.setText(stringContent)
                removeAllChildNodes()
                addChildNode(element)
                
                if let parent = parent() {
                    element.inheritAttributes(from: parent)
                } else {
                    fontDescriptor = DTCoreTextFontDescriptor()
                    fontDescriptor.fontFamily = font.familyName
                    fontDescriptor.fontName = font.fontName
                    fontDescriptor.pointSize = font.pointSize
                    paragraphStyle = DTCoreTextParagraphStyle.default()
                    
                    element.inheritAttributes(from: self)
                }
                element.interpretAttributes()
                
            } else if let parent = parent() {
                parent.removeChildNode(self)
            } else {
                didOutput = true
            }
            
        } else {
            // This element is a supported tag, but it may contain children that aren't,
            // so santize all child nodes to ensure correct tags.
            if let childNodes = childNodes as? [DTHTMLElement] {
                childNodes.forEach { $0.sanitize(font: font) }
            }
        }
    }
    
    private static let allowedHTMLTags = ["font", // custom to matrix for IRC-style font coloring
                                          "del", // for markdown
                                          "body", // added internally by DTCoreText
                                          "mx-reply",
                                          "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "p", "a", "ul", "ol",
                                          "nl", "li", "b", "i", "u", "strong", "em", "strike", "code", "hr", "br", "div",
                                          "table", "thead", "caption", "tbody", "tr", "th", "td", "pre"]
}
