/*   Copyright 2004 The Apache Software Foundation
 *
 *   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.
 */

package dom.common;

import org.junit.jupiter.api.Test;
import org.w3c.dom.CharacterData;
import org.w3c.dom.*;

import static org.junit.jupiter.api.Assertions.*;

public abstract class NodeWithChildrenTest extends NodeTest  {

    @Test
    void testRemoveChildEnd() {
        Node node = m_node.getLastChild();
        super.testRemoveChild(node);

    }

    @Test
    void testRemoveChild() {
        NodeList children = m_node.getChildNodes();
        int pos = children.getLength() / 2;
        Node node = children.item(pos);
        super.testRemoveChild(node);

    }

    @Test
    void testRemoveChildDiffImpl() throws Exception {
        Node toRemove = NodeTest.getApacheNode(sXml,true,'E');
        DOMException de = assertThrows(DOMException.class, () -> super.testRemoveChild(toRemove),
            "Removing node from a different impl");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    void testRemoveChildDiffDoc() {
        Node toRemove = m_docNS.getDocumentElement();
        DOMException de = assertThrows(DOMException.class,
            () -> super.testRemoveChild(toRemove), "Removing node from a different doc");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    void testRemoveChildFront() {
        Node node = m_node.getFirstChild();
        super.testRemoveChild(node);

    }

    @Test
    void testRemoveChildNull() {
        super.testRemoveChild(null);
    }

    @Test
    void testReplaceChild() {
        NodeList children = m_node.getChildNodes();
        int pos = children.getLength() / 2;
        Node newNode = (m_node instanceof Document)
            ? m_doc.createElement("fooBAR")
            : m_doc.createTextNode("fooBAR");
        Node node = children.item(pos);
        super.testReplaceChild(newNode, node);
    }

    @Test
    void testReplaceChildEnd() {
        Node node = m_node.getLastChild();
        Node newNode = m_doc.createTextNode("fooBAR");
        super.testReplaceChild(newNode, node);
    }

    @Test
    void testReplaceChildFront() {
        Node node = m_node.getFirstChild();
        Node newNode = m_doc.createTextNode("fooBAR");
        super.testReplaceChild(newNode, node);
    }

    @Test
    void testReplaceChildNullChild() {
        Node node = m_node.getChildNodes().item(0);
        assertNotNull(node);
        super.testReplaceChild(null, node);
    }

    @Test
    void testReplaceChildNull() {
        Node newNode = (m_node instanceof Document)
            ? ((Document) m_node).createElement("fooBAR")
            : m_node.getOwnerDocument().createElement("fooBAR");
        super.testReplaceChild(newNode, null);
    }

    @Test
    void testReplaceChildDNE() {

        if (m_doc == null) {
            assertEquals(m_doc, m_node.getOwnerDocument());
        }

        //node to replace is not a child
        Node node1 =m_doc.createElement("foobar");
        Node newNode1a = m_doc.createElement("fooBAR");
        try {
            super.testReplaceChild(newNode1a, node1);
        } catch (DOMException de) {
            assertEquals(DOMException.NOT_FOUND_ERR, de.code);//Raised if oldChild is not a child of this node.
        }

         //newChild was created from a different document than the one that created this node

        Node newNode1b = m_docNS.createElement("fooBAR");
        assertNotEquals(m_docNS, m_node.getOwnerDocument());
        DOMException de2 = assertThrows(DOMException.class, () -> super.testReplaceChild(newNode1b, node1), "Node is from the wrong document");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de2.code);

       //refChild was created from a different document than the one that created this node

        Node node2 = m_docNS.createElement("fooBAR");
        Node newNode2 =m_doc.createElement("fooBAR");
        DOMException de3 = assertThrows(DOMException.class, () -> super.testReplaceChild(newNode2, node2), "Node is from the wrong document");
        assertTrue((DOMException.WRONG_DOCUMENT_ERR == de3.code) || (DOMException.NOT_FOUND_ERR == de3.code));
    }


    // public void testInsertBeforeDiffDoc(){}:done above
    @Test
    void testReplace_replacement_DiffImpl() throws Exception {
        Node node = m_node.getFirstChild();
        Node newnode=NodeTest.getApacheNode(sXml,true,'T');
        DOMException de = assertThrows(DOMException.class, () -> super.testReplaceChild(newnode, node), "Inserting node created from a different impl");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    //ref child is diff impl
    @Test
    void testReplace_target_DiffImpl() throws Exception {
        Node node =NodeTest.getApacheNode(sXml,true,'E');
        Node newnode=m_node.getFirstChild();
        DOMException de = assertThrows(DOMException.class, () -> super.testReplaceChild(newnode, node), "Inserting node created from a different impl");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    public void testReplaceChildDocFrag() {
        DocumentFragment child = m_doc.createDocumentFragment();
        child.appendChild(m_doc.createElement("foo"));
        child.appendChild(m_doc.createElement("foobar"));
        Node toReplace = m_node.getFirstChild();
        super.testReplaceChild(child, toReplace);
    }

    @Test
    public void testInsertBefore() {
        Node target = m_node.getFirstChild();
        Node child = m_doc.createElementNS("org.foo.www", "foonode");
        assertNotNull(target);
        super.testInsertBefore(child, target);
    }

    @Test
    public void testInsertBeforeNullTarget() {
        Node child = m_doc.createElementNS("org.foo.www", "foonode");
        super.testInsertBefore(child, null);
    }

    @Test
    void testInsertBeforeInvalidRefNode() {
        Node child = m_doc.createElementNS("org.foo.www", "foonode");
        Node target = m_doc.createElement("foo");

        DOMException de = assertThrows(DOMException.class, () -> super.testInsertBefore(child, target), "Insert cannot happen");
        assertEquals(DOMException.NOT_FOUND_ERR, de.code);
    }

    @Test
    void testInsertBeforeNewChildDiffDoc(){
        Node target = m_node.getFirstChild();
        Node toInsert=m_docNS.getDocumentElement();
        DOMException de = assertThrows(DOMException.class, () -> super.testInsertBefore(toInsert, target), "Inserting node created from a different doc");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    void testInsertBeforeNewChildDiffImpl() throws Exception {
        Node target = m_node.getFirstChild();
        Node toInsert=NodeTest.getApacheNode(sXml,true,'T');
        DOMException de = assertThrows(DOMException.class, () -> super.testInsertBefore(toInsert, target), "Inserting node created from a different impl");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    void testInsertBeforeRefChildDiffDoc(){
        Node target = m_docNS.getDocumentElement();
        Node toInsert = m_node.getFirstChild();
        DOMException de = assertThrows(DOMException.class, () -> super.testInsertBefore(toInsert, target), "Ref Child from a different doc");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    @Test
    void testInsertBeforeRefChildDiffImpl() throws Exception {
        Node target = NodeTest.getApacheNode(sXml, true, 'T');
        Node toInsert = m_node.getFirstChild();
        DOMException de = assertThrows(DOMException.class, () -> super.testInsertBefore(toInsert, target));
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }


    @Test
    void testInsertBeforeNullChild() {
        Node target = m_doc.createElement("foo");
        super.testInsertBefore(null, target);
    }

    /**
     *  pre: child is not a parent ancestor
     */
    public void testAppendChildExisting(Node child) {
        if (child == m_node)
            child = m_doc.getLastChild();
        //if still the same, too bad
        super.testAppendChild(child);
    }

    /**
     * pre: child cannot be an ancestor of m_node
   */
    public void testInsertExistingNode(Node child) {
        Node target = m_node.getFirstChild();
        if (target != null && child != null && target.getParentNode()==child.getParentNode())
            child=child.getParentNode();
        assertFalse(target == null || child == null);
        super.testInsertBefore(child, target);
    }

    @Test
    public void testInsertBeforeDocFrag() {
        DocumentFragment child = m_doc.createDocumentFragment();
        child.appendChild(m_doc.createElement("foo1"));
        Node target = m_node.getFirstChild();
        super.testInsertBefore(child, target);
    }

    @Test
    public void testAppendChild() {
        Node newNode = m_doc.createElement("foo");
        super.testAppendChild(newNode);
    }

    //try to append the parent
    @Test
    void testAppendChildIllegal0() {
        Node parent = m_node.getFirstChild();
        m_node = m_node.getFirstChild();
        DOMException de = assertThrows(DOMException.class, () -> super.testAppendChild(parent), "Appending parent");
        assertEquals(DOMException.HIERARCHY_REQUEST_ERR, de.code);
    }

    //try to insert diff doc
    @Test
    void testAppendChildIllegal1() {
        Node newNode = m_docNS.createElement("newNode");
        DOMException de = assertThrows(DOMException.class, () -> super.testAppendChild(newNode), "Appending wrong doc");
        assertEquals(DOMException.WRONG_DOCUMENT_ERR, de.code);
    }

    //append doc frag
    @Test
    public void testAppendChildDocFrag() {
        DocumentFragment child = m_doc.createDocumentFragment();
        child.appendChild(m_doc.createElement("foo"));
        super.testAppendChild(child);
    }

    //TODO  : not implemented
    @Test
    void testNormalize() {
        int nCount=m_node.getChildNodes().getLength();
        String value="";
        if (m_node.getLastChild() instanceof Text)
            value= m_node.getLastChild().getNodeValue();

        int nExistingText=0;
        for (int i=nCount-1; i > -1; i--)
            if (m_node.getChildNodes().item(i) instanceof CharacterData)
                   nExistingText++;
        Node txt=m_doc.createTextNode("foo");
        m_node.appendChild(txt);

        txt=m_doc.createTextNode("");
        m_node.appendChild(txt);
        txt=m_doc.createTextNode(" bar");
        m_node.appendChild(txt);

        assertEquals(nCount + 3, m_node.getChildNodes().getLength());

        m_node.normalize();

        assertTrue((m_node.getLastChild() instanceof Text));
       // if (value.length()==0)nCount++;//if last node was a text nCount stays the same
        assertEquals(nCount - nExistingText + 1, m_node.getChildNodes().getLength());

        value+="foo bar";
        assertEquals(value, m_node.getLastChild().getNodeValue());
    }


    @Test
    void testSetPrefixInvalid() {
        //test only applies to Attrs and Elems
        if (!(m_node.getNodeType() == Node.ATTRIBUTE_NODE
            || m_node.getNodeType() == Node.ELEMENT_NODE))
            return;

        //qualifiedName is malformed
        DOMException de1 = assertThrows(DOMException.class, () -> m_node.setPrefix("invalid<"), "Invalid prefix name--see http://www.w3.org/TR/REC-xml#NT-BaseChar");
        assertEquals(DOMException.INVALID_CHARACTER_ERR, de1.code);

        //the qualifiedName has a prefix and the namespaceURI is null

        DOMException de2;
        if (m_node.getNamespaceURI() == null) {
            de2 = assertThrows(DOMException.class, () -> m_node.setPrefix("foo"), "Can not set prefix here");
        } else {
            de2 = assertThrows(DOMException.class, () -> m_node.setPrefix("xml"), "Xml is not a valid prefix here");
        }
        assertEquals(DOMException.NAMESPACE_ERR, de2.code);
    }

    @Test
    void testSetNodeValue() {
        int nCount = m_node.getChildNodes().getLength();

		// verify before setting value
		for (int i = 0; i < nCount; i++) {
			assertNotEquals("blah", m_node.getChildNodes().item(i).getNodeValue(),
					"Failed check before change at " + i + " of " + nCount);
		}

        m_node.setNodeValue("blah");

		// verify after setting value
        assertEquals(nCount, m_node.getChildNodes().getLength());
        for (int i = 0; i < nCount; i++) {
			assertNotEquals("blah", m_node.getChildNodes().item(i).getNodeValue(),
					"Failed at " + i + " of " + nCount);
		}
    }
}
