/*
 * Copyright 2004-2005 The Trix Development Team.
 *
 * 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 org.trix.cuery;

import java.io.IOException;

import junit.framework.TestCase;

import org.trix.cuery.property.Property;
import org.trix.cuery.util.CSSUtil;
import org.trix.cuery.util.DOMUtil;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * DOCUMENT.
 * 
 * @author <a href="mailto:Teletha.T@gmail.com">Teletha Testarossa</a>
 * @version $ Id: CSSWeaverTest.java,v 1.03 2005/08/25 21:47:39 Teletha Exp $
 */
public class CSSWeaverTest extends TestCase {

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplySimpleStyle() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test001.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test001.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleFromSeveralSource1() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test002-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test002-author.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test002.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleFromSeveralSource2() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test003-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test003-author.css"));
        weaver.addUserStylesheet(CSSUtil.getSource("src/test/resource/weaver/test003-user.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test003.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleWithImportant1() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test004-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test004-author.css")); // important
        weaver.addUserStylesheet(CSSUtil.getSource("src/test/resource/weaver/test004-user.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test004.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleWithImportant2() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test005-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test005-author.css"));
        weaver.addUserStylesheet(CSSUtil.getSource("src/test/resource/weaver/test005-user.css")); // important

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test005.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("right", property.getValueAsString("clear"));
        assertEquals("compact", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleWithImportant3() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test006-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test006-author.css")); // important
        weaver.addUserStylesheet(CSSUtil.getSource("src/test/resource/weaver/test006-user.css")); // important

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test006.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("right", property.getValueAsString("clear"));
        assertEquals("compact", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyInlineStyle() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareXMLStylesheet(true);

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test007.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    public void testApplyStyleWithInlineStyle1() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareXMLStylesheet(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test008-agent.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test008.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Inline stylesheet as author's style, but it must have latter position.
     */
    public void testApplyStyleWithInlineStyle2() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareXMLStylesheet(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test009-agent.css"));
        weaver.addAuthorStylesheet(CSSUtil.getSource("src/test/resource/weaver/test009-author.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test009.xml");
        Element element = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(element);

        assertEquals("both", property.getValueAsString("clear"));
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test StyleContext mutation.
     */
    public void testMutation1() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareDOMMutation(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test010.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test010.xml");
        Element target = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(target);
        assertEquals("block", property.getValueAsString("display"));

        // change state :hover
        StyleContext context = StyleContext.getContext(target);
        context.assign(CSS.HOVER);
        assertEquals("inline", property.getValueAsString("display"));

        // change state :hover:focus
        context.assign(CSS.FOCUS);
        assertEquals("compact", property.getValueAsString("display"));

        // change state :focus
        context.deprive(CSS.HOVER);
        assertEquals("run-in", property.getValueAsString("display"));
    }

    /*
     * Test DOM node mutation.
     */
    public void testMutation2() throws Exception {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareDOMMutation(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test011.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test011.xml");
        Element target = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(target); // this is a last child
        assertEquals("block", property.getValueAsString("display"));

        // dynamic addition : insert new last child
        Element addition = document.createElementNS(null, "addition");
        document.getDocumentElement().appendChild(addition);

        assertEquals("inline", property.getValueAsString("display"));

        // assert new last child has a property 'display : block'
        property = StyleContext.getProperty(addition);
        assertEquals("block", property.getValueAsString("display"));
    }

    /*
     * Test DOM node mutation with structured elements.
     */
    public void testMutation3() throws IOException {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareDOMMutation(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test012.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test012.xml");

        // dynamic addition : new structured element
        Element addition = document.createElementNS(null, "addition");
        Element child = document.createElementNS(null, "child");
        addition.appendChild(child);
        document.getDocumentElement().appendChild(addition);

        Property property = StyleContext.getProperty(addition);
        assertEquals("compact", property.getValueAsString("display"));

        property = StyleContext.getProperty(child);
        assertEquals("run-in", property.getValueAsString("display"));
    }

    /*
     * Test DOM node mutation with remove elements.
     */
    public void testMutation4() throws IOException {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareDOMMutation(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test013.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test013.xml");
        Element item1 = DOMUtil.getElementById(document, "item1");
        Element item2 = DOMUtil.getElementById(document, "item2");
        Element item3 = DOMUtil.getElementById(document, "item3");

        Property property1 = StyleContext.getProperty(item1);
        Property property2 = StyleContext.getProperty(item2);
        Property property3 = StyleContext.getProperty(item3);

        assertEquals("inline", property1.getValueAsString("display"));
        assertEquals("inline", property2.getValueAsString("display"));
        assertEquals("block", property3.getValueAsString("display"));

        // dynamic remove
        document.getDocumentElement().removeChild(item3);

        assertEquals("inline", property1.getValueAsString("display"));
        assertEquals("block", property2.getValueAsString("display"));
        // assertEquals("inline", property3.getValueAsString("display")); // reset style information

        // dynamic remove
        document.getDocumentElement().removeChild(item2);

        assertEquals("block", property1.getValueAsString("display"));
        // assertEquals("inline", property2.getValueAsString("display")); // reset style information
        // assertEquals("inline", property3.getValueAsString("display")); // reset style information
    }

    /*
     * Test DOM attribute mutation.
     */
    public void testMutation5() throws IOException {
        CSSWeaver weaver = new CSSWeaver();
        weaver.awareDOMMutation(true);
        weaver.addAgentStylesheet(CSSUtil.getSource("src/test/resource/weaver/test014.css"));

        // apply style
        Document document = weaver.apply("src/test/resource/weaver/test014.xml");
        Element target = DOMUtil.getElementById(document, "target");
        Property property = StyleContext.getProperty(target);
        assertEquals("block", property.getValueAsString("display"));

        // dynamic addition : append attribute
        target.setAttribute("attr", "addition");

        assertEquals("compact", property.getValueAsString("display"));

        // dynamic addition : modify attribute
        target.setAttribute("attr", "modified");

        assertEquals("run-in", property.getValueAsString("display"));
    }

    /*
     * Test method for 'org.trix.cuery.CSSWeaver.apply(Document)'
     */
    // public void testImport() throws IOException {
    // CSSWeaver weaver = new CSSWeaver();
    // weaver.addUserStylesheet(CSSUtil.getSource("src/test/org/trix/cuery/cascadingOrder.css"));
    // Document document = weaver.apply("src/test/org/trix/cuery/cssWeaver.xml");
    //
    // Element heading = DOMUtil.getElementById(document, "heading1");
    // Property property = CSSWeaver.getProperty(heading);
    // assertEquals("justify", property.getValueAsString("text-align"));
    //
    // // check import
    // assertEquals("underline", property.getValueAsString("text-decoration"));
    // }
}
