/*
 * 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.models.jacksonexporter.impl;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ResolvableSerializer;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map;

import static javax.xml.bind.JAXBIntrospector.getValue;

public class ResourceSerializer extends JsonSerializer<Resource> implements ResolvableSerializer {

    private final int maxRecursionLevels;
    private JsonSerializer<Object> calendarSerializer;

    public ResourceSerializer(int maxRecursionLevels) {
        this.maxRecursionLevels = maxRecursionLevels;
    }

    @Override
    public void serialize(final Resource value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
        create(value, jgen, 0, provider);
    }

    /** Dump given resource in JSON, optionally recursing into its objects */
    private void create(final Resource resource, final JsonGenerator jgen, final int currentRecursionLevel,
                                     final SerializerProvider provider) throws IOException {
        jgen.writeStartObject();

        final ValueMap valueMap = resource.adaptTo(ValueMap.class);

        final Map propertyMap = (valueMap != null) ? valueMap : resource.adaptTo(Map.class);

        if (propertyMap == null) {

            // no map available, try string
            final String value = resource.adaptTo(String.class);
            if (value != null) {

                // single value property or just plain String resource or...
                jgen.writeStringField(resource.getName(), value);

            } else {

                // Try multi-value "property"
                final String[] values = resource.adaptTo(String[].class);
                if (values != null) {
                    jgen.writeArrayFieldStart(resource.getName());
                    for (final String s : values) {
                        jgen.writeString(s);
                    }
                    jgen.writeEndArray();
                }

            }

        } else {

            @SuppressWarnings("unchecked")
            final Iterator<Map.Entry> props = propertyMap.entrySet().iterator();

            // the node's actual properties
            while (props.hasNext()) {
                final Map.Entry prop = props.next();

                if (prop.getValue() != null) {
                    createProperty(jgen, valueMap, prop.getKey().toString(), prop.getValue(), provider);
                }
            }
        }

        // the child nodes
        if (recursionLevelActive(currentRecursionLevel)) {
            for (final Resource n : resource.getChildren()) {
                jgen.writeObjectFieldStart(n.getName());
                create(n, jgen, currentRecursionLevel + 1, provider);
            }
        }

        jgen.writeEndObject();
    }

    /**
     * Write a single property
     */
    private void createProperty(final JsonGenerator jgen, final ValueMap valueMap, final String key, final Object value,
                                final SerializerProvider provider)
            throws IOException {
        Object[] values = null;
        if (value.getClass().isArray()) {
            final int length = Array.getLength(value);
            // write out empty array
            if ( length == 0 ) {
                jgen.writeArrayFieldStart(key);
                jgen.writeEndArray();
                return;
            }
            values = new Object[Array.getLength(value)];
            for(int i=0; i<length; i++) {
                values[i] = Array.get(value, i);
            }
        }

        // special handling for binaries: we dump the length and not the data!
        if (value instanceof InputStream
                || (values != null && values[0] instanceof InputStream)) {
            // TODO for now we mark binary properties with an initial colon in
            // their name
            // (colon is not allowed as a JCR property name)
            // in the name, and the value should be the size of the binary data
            if (values == null) {
                jgen.writeNumberField(":" + key, getLength(valueMap, -1, key, (InputStream)value));
            } else {
                jgen.writeArrayFieldStart(":" + key);
                for (int i = 0; i < values.length; i++) {
                    jgen.writeNumber(getLength(valueMap, i, key, (InputStream)values[i]));
                }
                jgen.writeEndArray();
            }
            return;
        }

        if (!value.getClass().isArray()) {
            jgen.writeFieldName(key);
            writeValue(jgen, value, provider);
        } else {
            jgen.writeArrayFieldStart(key);
            for (Object v : values) {
                writeValue(jgen, v, provider);
            }
            jgen.writeEndArray();
        }
    }

    /** true if the current recursion level is active */
    private boolean recursionLevelActive(final int currentRecursionLevel) {
        return maxRecursionLevels < 0 || currentRecursionLevel < maxRecursionLevels;
    }

    private long getLength(final ValueMap valueMap, final int index, final String key, final InputStream stream) {
        try {
            stream.close();
        } catch (IOException ignore) {}

        long length = -1;
        if ( valueMap != null ) {
            if ( index == -1 ) {
                length = valueMap.get(key, length);
            } else {
                Long[] lengths = valueMap.get(key, Long[].class);
                if ( lengths != null && lengths.length > index ) {
                    length = lengths[index];
                }
            }
        }
        return length;
    }

    /** Dump only a value in the correct format */
    private void writeValue(final JsonGenerator jgen, final Object value, final SerializerProvider provider) throws IOException {
        if (value instanceof InputStream) {
            // input stream is already handled
            jgen.writeNumber(0);
        } else if (value instanceof Calendar) {
            calendarSerializer.serialize(value, jgen, provider);
        } else if (value instanceof Boolean) {
            jgen.writeBoolean(((Boolean)value).booleanValue());
        } else if (value instanceof Long) {
            jgen.writeNumber(((Long)value).longValue());
        } else if (value instanceof Integer) {
            jgen.writeNumber(((Integer)value).intValue());
        } else if (value instanceof Double) {
            jgen.writeNumber(((Double)value).doubleValue());
        } else if (value != null) {
            jgen.writeString(value.toString());
        } else {
            jgen.writeString(""); // assume empty string
        }
    }

    @Override
    public void resolve(SerializerProvider provider) throws JsonMappingException {
        this.calendarSerializer = provider.findValueSerializer(Calendar.class, null);
    }
}
