/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.sling.ide.impl.vlt.serialization;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.array;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.sling.ide.impl.vlt.Slf4jLogger;
import org.apache.sling.ide.transport.ResourceProxy;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class ContentXmlHandlerTest {

    @Test
    public void simpleContentXml() throws ParserConfigurationException, SAXException, IOException {

        Map<String, Object> properties = parseContentXmlFile("simple-content.xml", "/").getProperties();

        assertThat("properties.size", properties.size(), is(12));

        assertThat("properties[jcr:primaryType]", properties, hasEntry("jcr:primaryType", (Object) "sling:Folder"));
        assertThat("properties[jcr:title]", properties, hasEntry("jcr:title", (Object) "Application folder"));
        assertThat("properties[indexed]", properties, hasEntry("indexed", (Object) Boolean.TRUE));
        assertThat("properties[indexRatio]", properties, hasEntry("indexRatio", (Object) Double.valueOf(2.54)));
        assertThat("properties[indexDuration]", properties, hasEntry("indexDuration", (Object) BigDecimal.valueOf(500)));
        assertThat("properties[lastIndexTime]", (Calendar) properties.get("lastIndexTime"),
                is(millis(1378292400000l)));
        assertThat("properties[lastIndexId]", properties,
                hasEntry("lastIndexId", (Object) Long.valueOf(7293120000000l)));
        assertThat("properties[lastIndexId]", properties,
                hasEntry("lastIndexId", (Object) Long.valueOf(7293120000000l)));
        assertThat("properties[emptyValue]", properties, hasEntry("emptyValue", (Object) ""));

    }

    private ResourceProxy parseContentXmlFile(String fileName, String rootResourcePath)
            throws ParserConfigurationException, SAXException,
            IOException {

        InputSource source = new InputSource(getClass().getResourceAsStream(fileName));

        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
        SAXParser parser = factory.newSAXParser();
        ContentXmlHandler handler = new ContentXmlHandler(rootResourcePath, new Slf4jLogger());
        parser.parse(source, handler);

        return handler.getRoot();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void parseMultiValuedProperties() throws ParserConfigurationException, SAXException, IOException {

        Map<String, Object> properties = parseContentXmlFile("multivalued-properties-content.xml", "/").getProperties();

        assertThat("properties.size", properties.size(), is(7));
        assertThat("properties[values]", (String[]) properties.get("values"),
                Matchers.is(new String[] { "first", "second" }));
        assertThat("properties[decimals]", (BigDecimal[]) properties.get("decimals"),
                Matchers.is(new BigDecimal[] { new BigDecimal("5.10"), new BigDecimal("5.11") }));
        assertThat("properties[doubles]", (Double[]) properties.get("doubles"),
                Matchers.is(new Double[] { new Double("5.1"), new Double("7.5"), new Double("9.0") }));
        assertThat("properties[flags]", (Boolean[]) properties.get("flags"),
                Matchers.is(new Boolean[] { Boolean.FALSE, Boolean.TRUE }));
        assertThat("properties[longs]", (Long[]) properties.get("longs"),
                Matchers.is(new Long[] { Long.valueOf(15), Long.valueOf(25) }));
        assertThat("properties[dates]", (Calendar[]) properties.get("dates"), array(
                millis(1377982800000l), millis(1378242000000l)));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void parseSingleExplicitMultiValuedProperties() throws ParserConfigurationException, SAXException,
            IOException {

        Map<String, Object> properties = parseContentXmlFile("single-explicit-multivalued-properties-content.xml", "/")
                .getProperties();

        assertThat("properties.size", properties.size(), is(7));
        assertThat("properties[values]", (String[]) properties.get("values"),
                Matchers.is(new String[] { "first"}));
        assertThat("properties[decimals]", (BigDecimal[]) properties.get("decimals"),
                Matchers.is(new BigDecimal[] { new BigDecimal("5.10")}));
        assertThat("properties[doubles]", (Double[]) properties.get("doubles"),
                Matchers.is(new Double[] { new Double("5.1") }));
        assertThat("properties[flags]", (Boolean[]) properties.get("flags"),
                Matchers.is(new Boolean[] { Boolean.FALSE }));
        assertThat("properties[longs]", (Long[]) properties.get("longs"),
                Matchers.is(new Long[] { Long.valueOf(15)}));
        assertThat("properties[dates]", (Calendar[]) properties.get("dates"),
                array(millis(1377982800000l)));
    }

    @Test
    public void parseFullCoverageXmlFile() throws ParserConfigurationException, SAXException, IOException {

        ResourceProxy root = parseContentXmlFile("full-coverage.xml", "/apps/full-coverage");

        assertThat("full-coverage path", root.getPath(), is("/apps/full-coverage"));
        assertThat("full-coverage properties.size", root.getProperties().size(), is(3));
        assertThat("full-coverage properties[jcr:title]", root.getProperties(),
                hasEntry("jcr:title", (Object) "Full coverage parent"));
        assertThat("full-coverage children.size", root.getChildren().size(), is(2));

        ResourceProxy parent1 = root.getChildren().get(0);
        assertThat("parent-1 path", parent1.getPath(), is("/apps/full-coverage/parent-1"));
        assertThat("parent-1 properties[jcr:title]", parent1.getProperties(),
                hasEntry("jcr:title", (Object) "Parent 1"));
        assertThat("parent-1 children.size", parent1.getChildren().size(), is(2));

        ResourceProxy child11 = parent1.getChildren().get(0);
        assertThat("child-1-1 path", child11.getPath(), is("/apps/full-coverage/parent-1/child-1-1"));
        assertThat("child-1-1 properties[jcr:title]", child11.getProperties(),
                hasEntry("jcr:title", (Object) "Child 1-1"));

    }

    @Test
    public void parseRootContentXml() throws ParserConfigurationException, SAXException, IOException {

        ResourceProxy root = parseContentXmlFile("root-content.xml", "/");

        assertThat("root contains /jcr:system", root.getChildren(), hasChildPath("/jcr:system"));
    }

    @Test
    public void encodedChildContentXml() throws ParserConfigurationException, SAXException, IOException {

        ResourceProxy root = parseContentXmlFile("encoded-child-content.xml", "/ROOT");

        assertThat("/ROOT contains /_jcr_content", root.getChildren(), hasChildPath("/ROOT/_jcr_content"));
    }

    @Test
    public void parseContentXmlWithEscapedNames() throws ParserConfigurationException, SAXException, IOException {

        ResourceProxy root = parseContentXmlFile("full-coverage-escaped-names.xml", "/");
        assertThat("node contains /50-50", root.getChildren(), hasChildPath("/50-50"));
    }

    @Test
    public void parseContentXmlWithBinaryProperty() throws ParserConfigurationException, SAXException, IOException {

        ResourceProxy root = parseContentXmlFile("binary-property.xml", "/");

        assertThat("root has 1 property, binary property is ignored", root.getProperties().entrySet(), hasSize(1));
    }

    @Test
    public void parseContentXmlWithEscapedValues() throws ParserConfigurationException, SAXException, IOException {
        ResourceProxy root = parseContentXmlFile("escaped-value-in-property.xml", "/");

        assertThat(root.getProperties(), hasEntry("property", 
                (Object) "{\"template\":\"<p class=\\\"contexthub-module-line1\\\">\"}"));
    }

    @Test
    public void escapedBraceAtStartOfPropertyValue() throws Exception {

        ResourceProxy root = parseContentXmlFile("escaped-braces-at-start-of-property.xml", "/");
        assertThat("properties[org.apache.sling.commons.log.pattern]",
                root.getProperties(), hasEntry("org.apache.sling.commons.log.pattern",
                        (Object) "{0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}"));
    }

    @Test
    public void escapedCommaInMultiValuedProperty() throws Exception {
        
        ResourceProxy root = parseContentXmlFile("escaped-comma-in-multi-valued-property.xml", "/");
        assertThat("properties[someProp]", (String[]) root.getProperties().get("someProp"),
                Matchers.is(new String[] { "first,first", "second" }));
    }
    
    @Test
    public void emptyMultivaluedProperties() throws Exception {
        
        ResourceProxy root = parseContentXmlFile("empty-multivalued-property.xml", "/");
        
        assertThat("properties[labels]", (String[]) root.getProperties().get("labels"),
                Matchers.arrayWithSize(0));
        assertThat("properties[values]", (Long[]) root.getProperties().get("values"),
                Matchers.arrayWithSize(0));
        
    }

    private static Matcher<Calendar> millis(long millis) {

        return new CalendarTimeInMillisMatcher(millis);
    }

    private static Matcher<Iterable<? extends ResourceProxy>> hasChildPath(String path) {

        return new ResourceChildPathMatcher(path);
    }

    static class CalendarTimeInMillisMatcher extends TypeSafeMatcher<Calendar> {

        private final long timeInMillis;

        private CalendarTimeInMillisMatcher(long timeInMillis) {
            this.timeInMillis = timeInMillis;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("getTimeInMillis() does not equal ").appendValue(timeInMillis);
        }

        @Override
        protected boolean matchesSafely(Calendar item) {
            return timeInMillis == item.getTimeInMillis();
        }

    }

    static class ResourceChildPathMatcher extends TypeSafeMatcher<Iterable<? extends ResourceProxy>> {

        private final String resourcePath;

        private ResourceChildPathMatcher(String resourcePath) {

            this.resourcePath = resourcePath;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("Resource with path ").appendValue(resourcePath);
        }

        @Override
        protected boolean matchesSafely(Iterable<? extends ResourceProxy> item) {
            for (ResourceProxy resource : item) {
                if (resourcePath.equals(resource.getPath())) {
                    return true;
                }
            }
            return false;
        }
    }
}
