/*
 * 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.servlets.get.impl.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;

import org.apache.jackrabbit.util.ISO8601;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

public class JsonObjectCreator {

    /** Used to format date values */
    private static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";

    /** The Locale used to format date values */
    static final Locale DATE_FORMAT_LOCALE = Locale.US;

    private Resource resource;

    private ValueMap valueMap;

    private boolean ecmaSupport;

    public JsonObjectCreator(Resource resource, boolean ecmaSupport) {
        this.resource = resource;
        this.valueMap = resource.getValueMap();
        this.ecmaSupport = ecmaSupport;
    }

    public JsonObjectBuilder create() {
        final JsonObjectBuilder obj = Json.createObjectBuilder();

        ValueMap valueMap = resource.getValueMap();
        if (valueMap.isEmpty()) {
            final String value = resource.adaptTo(String.class);
            if (value != null) {
                obj.add(resource.getName(), value.toString());
            } else {
                final String[] values = resource.adaptTo(String[].class);
                if (values != null) {
                    JsonArrayBuilder builder = Json.createArrayBuilder();
                    for (String v : values) {
                        builder.add(v);
                    }
                    obj.add(resource.getName(), builder);
                }
            }
            return obj;
        }

        final Iterator<Map.Entry<String, Object>> props = valueMap.entrySet().iterator();

        while (props.hasNext()) {
            final Map.Entry<String, Object> prop = props.next();
            if (prop.getValue() != null) {
                createProperty(obj, prop.getKey(), prop.getValue());
            }
        }

        return obj;
    }

    public static String formatEcma(final Calendar date) {
        DateFormat formatter = new SimpleDateFormat(ECMA_DATE_FORMAT, DATE_FORMAT_LOCALE);
        formatter.setTimeZone(date.getTimeZone());
        return formatter.format(date.getTime());
    }

    /** Dump only a value in the correct format */
    private JsonValue getValue(final Object value) {
        JsonObjectBuilder builder = Json.createObjectBuilder();

        if (value instanceof InputStream) {
            // input stream is already handled
            builder.add("entry", 0);
        } else if (value instanceof Calendar) {
            if (ecmaSupport) {
                builder.add("entry", JsonObjectCreator.formatEcma((Calendar) value));
            } else {
                builder.add("entry", ISO8601.format(((Calendar) value)));
            }
        } else if (value instanceof Boolean) {
            builder.add("entry", (Boolean) value);
        } else if (value instanceof Long) {
            builder.add("entry", (Long) value);
        } else if (value instanceof Double) {
            builder.add("entry", (Double) value);
        } else if (value != null) {
            builder.add("entry", value.toString());
        } else {
            builder.add("entry", "");
        }
        return builder.build().get("entry");
    }

    /**
     * Write a single property
     */
    private void createProperty(final JsonObjectBuilder obj, final String key, final Object value) {
        Object[] values = null;
        if (value.getClass().isArray()) {
            final int length = Array.getLength(value);
            // write out empty array
            if (length == 0) {
                obj.add(key, Json.createArrayBuilder());
                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) {
                obj.add(":" + key, getLength(0, key, (InputStream) value));
            } else {
                final JsonArrayBuilder result = Json.createArrayBuilder();
                for (int i = 0; i < values.length; i++) {
                    result.add(getLength(i, key, (InputStream) values[i]));
                }
                obj.add(":" + key, result);
            }
            return;
        }

        if (!value.getClass().isArray()) {
            obj.add(key, getValue(value));
        } else {
            final JsonArrayBuilder result = Json.createArrayBuilder();
            for (Object v : values) {
                result.add(getValue(v));
            }
            obj.add(key, result);
        }
    }

    private long getLength(final int index, final String key, final InputStream stream) {
        try {
            stream.close();
        } catch (IOException ignore) {
        }
        long length = -1;
        if (valueMap != null) {
            Long[] lengths = valueMap.get(key, Long[].class);
            if (lengths != null && lengths.length > index) {
                length = lengths[index];
            }
        }
        return length;
    }
}
