// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//

import CoreFoundation
// Input options
//  NSXMLNodeOptionsNone
//  NSXMLNodePreserveAll
//  NSXMLNodePreserveNamespaceOrder
//  NSXMLNodePreserveAttributeOrder
//  NSXMLNodePreserveEntities
//  NSXMLNodePreservePrefixes
//  NSXMLNodePreserveCDATA
//  NSXMLNodePreserveEmptyElements
//  NSXMLNodePreserveQuotes
//  NSXMLNodePreserveWhitespace
//  NSXMLNodeLoadExternalEntities
//  NSXMLNodeLoadExternalEntitiesSameOriginOnly

//  NSXMLDocumentTidyHTML
//  NSXMLDocumentTidyXML

//  NSXMLDocumentValidate

// Output options
//  NSXMLNodePrettyPrint
//  NSXMLDocumentIncludeContentTypeDeclaration

extension XMLDocument {

    /*!
        @typedef XMLDocument.ContentKind
        @abstract Define what type of document this is.
        @constant XMLDocument.ContentKind.xml The default document type
        @constant XMLDocument.ContentKind.xhtml Set if XMLNode.Options.documentTidyHTML is set and HTML is detected
        @constant XMLDocument.ContentKind.html Outputs empty tags without a close tag, eg <br>
        @constant XMLDocument.ContentKind.text Output the string value of the document
    */
    public enum ContentKind : UInt {

        case xml
        case xhtml
        case html
        case text
    }
}

/*!
    @class XMLDocument
    @abstract An XML Document
	@discussion Note: if the application of a method would result in more than one element in the children array, an exception is thrown. Trying to add a document, namespace, attribute, or node with a parent also throws an exception. To add a node with a parent first detach or create a copy of it.
*/
open class XMLDocument : XMLNode {
    private var _xmlDoc: _CFXMLDocPtr {
        return _CFXMLDocPtr(_xmlNode)
    }
    
    public init() {
        NSUnimplemented()
    }
    
    /*!
        @method initWithXMLString:options:error:
        @abstract Returns a document created from either XML or HTML, if the HTMLTidy option is set. Parse errors are returned in <tt>error</tt>.
    */
    public convenience init(xmlString string: String, options mask: XMLNode.Options = []) throws {
        guard let data = string.data(using: .utf8) else {
            // TODO: Throw an error
            fatalError("String: '\(string)' could not be converted to NSData using UTF-8 encoding")
        }

        try self.init(data: data, options: mask)
    }

    /*!
        @method initWithContentsOfURL:options:error:
        @abstract Returns a document created from the contents of an XML or HTML URL. Connection problems such as 404, parse errors are returned in <tt>error</tt>.
    */
    public convenience init(contentsOf url: URL, options mask: XMLNode.Options = []) throws {
        let data = try Data(contentsOf: url, options: .mappedIfSafe)

        try self.init(data: data, options: mask)
    }

    /*!
        @method initWithData:options:error:
        @abstract Returns a document created from data. Parse errors are returned in <tt>error</tt>.
    */
    public init(data: Data, options mask: XMLNode.Options = []) throws {
        let docPtr = _CFXMLDocPtrFromDataWithOptions(data._cfObject, Int32(mask.rawValue))
        super.init(ptr: _CFXMLNodePtr(docPtr))

        if mask.contains(.documentValidate) {
            try validate()
        }
    }

    /*!
        @method initWithRootElement:
        @abstract Returns a document with a single child, the root element.
    */
    public init(rootElement element: XMLElement?) {
        precondition(element?.parent == nil)

        super.init(kind: .document, options: [])
        if let element = element {
            _CFXMLDocSetRootElement(_xmlDoc, element._xmlNode)
            _childNodes.insert(element)
        }
    }

    open class func replacementClass(for cls: AnyClass) -> AnyClass {
        NSUnimplemented()
    }

    /*!
        @method characterEncoding
        @abstract Sets the character encoding to an IANA type.
    */
    open var characterEncoding: String? {
        get {
            return _CFXMLDocCopyCharacterEncoding(_xmlDoc)?._swiftObject
        }
        set {
            if let value = newValue {
                _CFXMLDocSetCharacterEncoding(_xmlDoc, value)
            } else {
                _CFXMLDocSetCharacterEncoding(_xmlDoc, nil)
            }
        }
    }

    /*!
        @method version
        @abstract Sets the XML version. Should be 1.0 or 1.1.
    */
    open var version: String? {
        get {
            return _CFXMLDocCopyVersion(_xmlDoc)?._swiftObject
        }
        set {
            if let value = newValue {
                precondition(value == "1.0" || value == "1.1")
                _CFXMLDocSetVersion(_xmlDoc, value)
            } else {
                _CFXMLDocSetVersion(_xmlDoc, nil)
            }
        }
    }

    /*!
        @method standalone
        @abstract Set whether this document depends on an external DTD. If this option is set the standalone declaration will appear on output.
    */
    open var isStandalone: Bool {
        get {
            return _CFXMLDocStandalone(_xmlDoc)
        }
        set {
            _CFXMLDocSetStandalone(_xmlDoc, newValue)
        }
    }//primitive

    /*!
        @method documentContentKind
        @abstract The kind of document.
    */
    open var documentContentKind: XMLDocument.ContentKind  {
        get {
            let properties = _CFXMLDocProperties(_xmlDoc)

            if properties & Int32(_kCFXMLDocTypeHTML) != 0 {
                return .html
            }

            return .xml
        }

        set {
            var properties = _CFXMLDocProperties(_xmlDoc)
            switch newValue {
            case .html:
                properties |= Int32(_kCFXMLDocTypeHTML)

            default:
                properties &= ~Int32(_kCFXMLDocTypeHTML)
            }

            _CFXMLDocSetProperties(_xmlDoc, properties)
        }
    }//primitive

    /*!
        @method MIMEType
        @abstract Set the MIME type, eg text/xml.
    */
    open var mimeType: String?

    /*!
        @method DTD
        @abstract Set the associated DTD. This DTD will be output with the document.
    */
    /*@NSCopying*/ open var dtd: XMLDTD? {
        get {
            return XMLDTD._objectNodeForNode(_CFXMLDocDTD(_xmlDoc)!)
        }
        set {
            if let currDTD = _CFXMLDocDTD(_xmlDoc) {
                if _CFXMLNodeGetPrivateData(currDTD) != nil {
                    let DTD = XMLDTD._objectNodeForNode(currDTD)
                    _CFXMLUnlinkNode(currDTD)
                    _childNodes.remove(DTD)
                } else {
                    _CFXMLFreeDTD(currDTD)
                }
            }

            if let value = newValue {
                guard let dtd = value.copy() as? XMLDTD else {
                    fatalError("Failed to copy DTD")
                }
                _CFXMLDocSetDTD(_xmlDoc, dtd._xmlDTD)
                _childNodes.insert(dtd)
            } else {
                _CFXMLDocSetDTD(_xmlDoc, nil)
            }
        }
    }//primitive

    /*!
        @method setRootElement:
        @abstract Set the root element. Removes all other children including comments and processing-instructions.
    */
    open func setRootElement(_ root: XMLElement) {
        precondition(root.parent == nil)

        for child in _childNodes {
            child.detach()
        }

        _CFXMLDocSetRootElement(_xmlDoc, root._xmlNode)
        _childNodes.insert(root)
    }

    /*!
        @method rootElement
        @abstract The root element.
    */
    open func rootElement() -> XMLElement? {
        guard let rootPtr = _CFXMLDocRootElement(_xmlDoc) else {
            return nil
        }

        return XMLNode._objectNodeForNode(rootPtr) as? XMLElement
    }

    /*!
        @method insertChild:atIndex:
        @abstract Inserts a child at a particular index.
    */
    open func insertChild(_ child: XMLNode, at index: Int) {
        _insertChild(child, atIndex: index)
    }

    /*!
        @method insertChildren:atIndex:
        @abstract Insert several children at a particular index.
    */
    open func insertChildren(_ children: [XMLNode], at index: Int) {
        _insertChildren(children, atIndex: index)
    }

    /*!
        @method removeChildAtIndex:atIndex:
        @abstract Removes a child at a particular index.
    */
    open func removeChild(at index: Int) {
        _removeChildAtIndex(index)
    }

    /*!
        @method setChildren:
        @abstract Removes all existing children and replaces them with the new children. Set children to nil to simply remove all children.
    */
    open func setChildren(_ children: [XMLNode]?) {
        _setChildren(children)
    }

    /*!
        @method addChild:
        @abstract Adds a child to the end of the existing children.
    */
    open func addChild(_ child: XMLNode) {
        _addChild(child)
    }

    /*!
        @method replaceChildAtIndex:withNode:
        @abstract Replaces a child at a particular index with another child.
    */
    open func replaceChild(at index: Int, with node: XMLNode) {
        _replaceChildAtIndex(index, withNode: node)
    }

    /*!
        @method XMLData
        @abstract Invokes XMLDataWithOptions with XMLNode.Options.none.
    */
    /*@NSCopying*/ open var xmlData: Data { return xmlData() }

    /*!
        @method XMLDataWithOptions:
        @abstract The representation of this node as it would appear in an XML document, encoded based on characterEncoding.
    */
    open func xmlData(options: XMLNode.Options = []) -> Data {
        let string = xmlString(options: options)
        // TODO: support encodings other than UTF-8

        return string.data(using: .utf8) ?? Data()
    }

    /*!
        @method objectByApplyingXSLT:arguments:error:
        @abstract Applies XSLT with arguments (NSString key/value pairs) to this document, returning a new document.
    */
    open func object(byApplyingXSLT xslt: Data, arguments: [String : String]?) throws -> Any {
        NSUnimplemented()
    }

    /*!
        @method objectByApplyingXSLTString:arguments:error:
        @abstract Applies XSLT as expressed by a string with arguments (NSString key/value pairs) to this document, returning a new document.
    */
    open func object(byApplyingXSLTString xslt: String, arguments: [String : String]?) throws -> Any {
        NSUnimplemented()
    }

    /*!
        @method objectByApplyingXSLTAtURL:arguments:error:
        @abstract Applies the XSLT at a URL with arguments (NSString key/value pairs) to this document, returning a new document. Error may contain a connection error from the URL.
    */
    open func objectByApplyingXSLT(at xsltURL: URL, arguments argument: [String : String]?) throws -> Any {
        NSUnimplemented()
    }

    open func validate() throws {
        var unmanagedError: Unmanaged<CFError>? = nil
        let result = _CFXMLDocValidate(_xmlDoc, &unmanagedError)
        if !result,
            let unmanagedError = unmanagedError {
            let error = unmanagedError.takeRetainedValue()
            throw error._nsObject
        }
    }

    internal override class func _objectNodeForNode(_ node: _CFXMLNodePtr) -> XMLDocument {
        precondition(_CFXMLNodeGetType(node) == _kCFXMLTypeDocument)

        if let privateData = _CFXMLNodeGetPrivateData(node) {
            return XMLDocument.unretainedReference(privateData)
        }

        return XMLDocument(ptr: node)
    }

    internal override init(ptr: _CFXMLNodePtr) {
        super.init(ptr: ptr)
    }
}
