/*
 * 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.jcr.resource.internal.helper.jcr;

import static javax.jcr.Property.JCR_CONTENT;
import static javax.jcr.Property.JCR_CREATED;
import static javax.jcr.Property.JCR_DATA;
import static javax.jcr.Property.JCR_ENCODING;
import static javax.jcr.Property.JCR_FROZEN_PRIMARY_TYPE;
import static javax.jcr.Property.JCR_LAST_MODIFIED;
import static javax.jcr.Property.JCR_MIMETYPE;
import static javax.jcr.nodetype.NodeType.NT_FILE;
import static javax.jcr.nodetype.NodeType.NT_FROZEN_NODE;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;

import org.apache.sling.api.resource.ResourceMetadata;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class JcrNodeResourceMetadata extends ResourceMetadata {

    private static final long serialVersionUID = 1L;

    /** default log */
    private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResourceMetadata.class);

    private final Node node;
    private Node contentNode;
    private boolean nodePromotionChecked = false;
    private long creationTime = -1;
    private boolean populated = false;

    public JcrNodeResourceMetadata(final Node inNode) {
        this.node = inNode;
    }

    private Node promoteNode() {
        // check stuff for nt:file nodes
        try {
            if ((!nodePromotionChecked) &&
                    (node.isNodeType(NT_FILE) ||
                            (node.isNodeType(NT_FROZEN_NODE) &&
                                    node.getProperty(JCR_FROZEN_PRIMARY_TYPE).getString().equals(NT_FILE)))) {
                creationTime = node.getProperty(JCR_CREATED).getLong();

                // continue our stuff with the jcr:content node
                // which might be nt:resource, which we support below
                // if the node is new, the content node might not exist yet
                if (!node.isNew() || node.hasNode(JCR_CONTENT)) {
                    contentNode = node.getNode(JCR_CONTENT);
                }
                nodePromotionChecked = true;
            }
        } catch (final RepositoryException re) {
            report(re);
        }
        return contentNode != null ? contentNode : node;
    }

    private void report(final RepositoryException re) {
        String nodePath = "<unknown node path>";
        try {
            nodePath = contentNode != null ? contentNode.getPath() : node.getPath();
        } catch (RepositoryException e) {
            // ignore
        }
        LOGGER.info("setMetaData: Problem extracting metadata information for {}", nodePath, re);
    }

    @Override
    public Object get(final Object key) {
        final Object result = super.get(key);
        if (result != null) {
            return result;
        }

        if (CREATION_TIME.equals(key)) {
            promoteNode();
            internalPut(CREATION_TIME, creationTime);
            return creationTime;
        } else if (CONTENT_TYPE.equals(key)) {
            String contentType = null;
            final Node targetNode = promoteNode();
            try {
                if (targetNode.hasProperty(JCR_MIMETYPE)) {
                    contentType = targetNode.getProperty(JCR_MIMETYPE).getString();
                }
            } catch (final RepositoryException re) {
                report(re);
            }

            internalPut(CONTENT_TYPE, contentType);
            return contentType;
        } else if (CHARACTER_ENCODING.equals(key)) {
            String characterEncoding = null;
            final Node targetNode = promoteNode();
            try {
                if (targetNode.hasProperty(JCR_ENCODING)) {
                    characterEncoding = targetNode.getProperty(JCR_ENCODING).getString();
                }
            } catch (final RepositoryException re) {
                report(re);
            }
            internalPut(CHARACTER_ENCODING, characterEncoding);
            return characterEncoding;
        } else if (MODIFICATION_TIME.equals(key)) {
            long modificationTime = -1;
            final Node targetNode = promoteNode();
            try {
                if (targetNode.hasProperty(JCR_LAST_MODIFIED)) {
                    // We don't check node type, so JCR_LASTMODIFIED might not be a long
                    final Property prop = targetNode.getProperty(JCR_LAST_MODIFIED);
                    try {
                        modificationTime = prop.getLong();
                    } catch (final ValueFormatException vfe) {
                        LOGGER.debug("Property {} cannot be converted to a long, ignored ({})",
                                prop.getPath(), vfe);
                    }
                }
            } catch (final RepositoryException re) {
                report(re);
            }
            internalPut(MODIFICATION_TIME, modificationTime);
            return modificationTime;
        } else if (CONTENT_LENGTH.equals(key)) {
            long contentLength = -1;
            final Node targetNode = promoteNode();
            try {
                // if the node has a jcr:data property, use that property
                if (targetNode.hasProperty(JCR_DATA)) {
                    final Property prop = targetNode.getProperty(JCR_DATA);
                    contentLength = JcrItemResource.getContentLength(prop);
                } else {
                    // otherwise try to follow default item trail
                    Item item = getPrimaryItem(targetNode);
                    while (item != null && item.isNode()) {
                        item = getPrimaryItem((Node) item);
                    }
                    if (item != null) {
                        final Property data = (Property) item;

                        // set the content length property as a side effect
                        // for resources which are not nt:file based and whose
                        // data is not in jcr:content/jcr:data this will lazily
                        // set the correct content length
                        contentLength = JcrItemResource.getContentLength(data);
                    }
                }
            } catch (final RepositoryException re) {
                report(re);
            }
            internalPut(CONTENT_LENGTH, contentLength);
            return contentLength;
        }
        return null;
    }

    private static Item getPrimaryItem(final Node node) throws RepositoryException {
        String name = node.getPrimaryNodeType().getPrimaryItemName();
        if (name == null) {
            return null;
        }
        if (node.hasProperty(name)) {
            return node.getProperty(name);
        } else if (node.hasNode(name)) {
            return node.getNode(name);
        } else {
            return null;
        }
    }

    private void populate() {
        if (populated) {
            return;
        }
        get(CREATION_TIME);
        get(CONTENT_TYPE);
        get(CHARACTER_ENCODING);
        get(MODIFICATION_TIME);
        get(CONTENT_LENGTH);
        populated = true;
    }

    @Override
    public @NotNull Set<Map.Entry<String, Object>> entrySet() {
        populate();
        return super.entrySet();
    }

    @Override
    public @NotNull Set<String> keySet() {
        populate();
        return super.keySet();
    }

    @Override
    public @NotNull Collection<Object> values() {
        populate();
        return super.values();
    }

    @Override
    public int size() {
        populate();
        return super.size();
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean containsKey(final Object key) {
        if (super.containsKey(key)) {
            return true;
        }
        return CREATION_TIME.equals(key) ||
                CONTENT_TYPE.equals(key) ||
                CHARACTER_ENCODING.equals(key) ||
                MODIFICATION_TIME.equals(key) ||
                CONTENT_LENGTH.equals(key);
    }

    @Override
    public boolean containsValue(final Object value) {
        if (super.containsValue(value)) {
            return true;
        }
        if (!populated) {
            populate();
            return super.containsValue(value);
        }
        return false;
    }
}
