/*
 * 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.jackrabbit.oak.plugins.value.jcr;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Calendar;

import javax.jcr.Binary;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;

import com.google.common.base.Objects;
import org.apache.jackrabbit.api.JackrabbitValue;
import org.apache.jackrabbit.api.binary.BinaryDownloadOptions;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.IllegalRepositoryStateException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.value.Conversions;
import org.apache.jackrabbit.oak.plugins.value.ErrorValue;
import org.apache.jackrabbit.oak.plugins.value.OakValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of {@link Value} based on {@code PropertyState}.
 */
class ValueImpl implements JackrabbitValue, OakValue {
    private static final Logger LOG = LoggerFactory.getLogger(ValueImpl.class);

    private final PropertyState propertyState;
    private final Type<?> type;
    private final int index;
    private final NamePathMapper namePathMapper;
    private final BlobAccessProvider blobAccessProvider;

    private InputStream stream = null;

    /**
     * Create a new {@code Value} instance
     * @param property  The property state this instance is based on
     * @param index  The index
     * @param namePathMapper The name/path mapping used for converting JCR names/paths to
     * the internal representation.
     * @param blobAccessProvider The blob access provider
     * @throws IllegalArgumentException if {@code index < propertyState.count()}
     * @throws RepositoryException if the underlying node state cannot be accessed
     */
    private ValueImpl(@NotNull PropertyState property, int index,
                      @NotNull NamePathMapper namePathMapper,
                      @NotNull BlobAccessProvider blobAccessProvider)
            throws RepositoryException {
        checkArgument(index < property.count());
        this.propertyState = checkNotNull(property);
        this.type = getType(property);
        this.index = index;
        this.namePathMapper = checkNotNull(namePathMapper);
        this.blobAccessProvider = checkNotNull(blobAccessProvider);
    }

    /**
     * Create a new {@code Value} instance
     * @param property  The property state this instance is based on
     * @param namePathMapper The name/path mapping used for converting JCR names/paths to
     * the internal representation.
     * @param blobAccessProvider The blob access provider
     * @throws IllegalArgumentException if {@code property.isArray()} is {@code true}.
     * @throws RepositoryException if the underlying node state cannot be accessed
     */
    ValueImpl(@NotNull PropertyState property,
              @NotNull NamePathMapper namePathMapper,
              @NotNull BlobAccessProvider blobAccessProvider)
            throws RepositoryException {
        this(checkSingleValued(property), 0, namePathMapper, checkNotNull(blobAccessProvider));
    }

    private static PropertyState checkSingleValued(PropertyState property) {
        checkArgument(!property.isArray());
        return property;
    }

    /**
     * Create a new {@code Value} instance
     * @param property  The property state this instance is based on
     * @param index  The index
     * @param namePathMapper The name/path mapping used for converting JCR names/paths to
     * the internal representation.
     * @param blobAccessProvider The blob access provider
     * @throws IllegalArgumentException if {@code index < propertyState.count()}
     */
    @NotNull
    static Value newValue(@NotNull PropertyState property, int index,
                          @NotNull NamePathMapper namePathMapper,
                          @NotNull BlobAccessProvider blobAccessProvider) {
        try {
            return new ValueImpl(property, index, namePathMapper, blobAccessProvider);
        } catch (RepositoryException e) {
            return new ErrorValue(e);
        }
    }

    /**
     * Create a new {@code Value} instance
     * @param property  The property state this instance is based on
     * @param namePathMapper The name/path mapping used for converting JCR names/paths to
     * the internal representation.
     * @param blobAccessProvider The blob access provider
     * @throws IllegalArgumentException if {@code property.isArray()} is {@code true}.
     */
    @NotNull
    static Value newValue(@NotNull PropertyState property,
                          @NotNull NamePathMapper namePathMapper,
                          @NotNull BlobAccessProvider blobAccessProvider) {
        try {
            return new ValueImpl(property, 0, namePathMapper, blobAccessProvider);
        } catch (RepositoryException e) {
            return new ErrorValue(e);
        }
    }

    //-----------------------------------------------------------< OakValue >---

    public Blob getBlob() throws RepositoryException {
        return getValue(Type.BINARY, index);
    }

    /**
     * Same as {@link #getString()} unless that names and paths are returned in their
     * Oak representation instead of being mapped to their JCR representation.
     * @return  A String representation of the value of this property.
     */
    public String getOakString() throws RepositoryException {
        return getValue(Type.STRING, index);
    }

    //--------------------------------------------------------------< Value >---

    /**
     * @see javax.jcr.Value#getType()
     */
    @Override
    public int getType() {
        return type.tag();
    }

    /**
     * @see javax.jcr.Value#getBoolean()
     */
    @Override
    public boolean getBoolean() throws RepositoryException {
        switch (getType()) {
            case PropertyType.STRING:
            case PropertyType.BINARY:
            case PropertyType.BOOLEAN:
                return getValue(Type.BOOLEAN, index);
            default:
                throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
        }
    }

    /**
     * @see javax.jcr.Value#getDate()
     */
    @Override
    public Calendar getDate() throws RepositoryException {
        try {
            switch (getType()) {
                case PropertyType.STRING:
                case PropertyType.BINARY:
                case PropertyType.DATE:
                    String value = getValue(Type.DATE, index);
                    return Conversions.convert(value).toCalendar();
                case PropertyType.LONG:
                case PropertyType.DOUBLE:
                case PropertyType.DECIMAL:
                    return Conversions.convert(getValue(Type.LONG, index)).toCalendar();
                default:
                    throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
            }
        }
        catch (IllegalArgumentException e) {
            throw new ValueFormatException("Error converting value to date", e);
        }
    }

    /**
     * @see javax.jcr.Value#getDecimal()
     */
    @Override
    public BigDecimal getDecimal() throws RepositoryException {
        try {
            switch (getType()) {
                case PropertyType.STRING:
                case PropertyType.BINARY:
                case PropertyType.LONG:
                case PropertyType.DOUBLE:
                case PropertyType.DATE:
                case PropertyType.DECIMAL:
                    return getValue(Type.DECIMAL, index);
                default:
                    throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
            }
        }
        catch (IllegalArgumentException e) {
            throw new ValueFormatException("Error converting value to decimal", e);
        }
    }

    /**
     * @see javax.jcr.Value#getDouble()
     */
    @Override
    public double getDouble() throws RepositoryException {
        try {
            switch (getType()) {
                case PropertyType.STRING:
                case PropertyType.BINARY:
                case PropertyType.LONG:
                case PropertyType.DOUBLE:
                case PropertyType.DATE:
                case PropertyType.DECIMAL:
                    return getValue(Type.DOUBLE, index);
                default:
                    throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
            }
        }
        catch (IllegalArgumentException e) {
            throw new ValueFormatException("Error converting value to double", e);
        }
    }

    /**
     * @see javax.jcr.Value#getLong()
     */
    @Override
    public long getLong() throws RepositoryException {
        try {
            switch (getType()) {
                case PropertyType.STRING:
                case PropertyType.BINARY:
                case PropertyType.LONG:
                case PropertyType.DOUBLE:
                case PropertyType.DATE:
                case PropertyType.DECIMAL:
                    return getValue(Type.LONG, index);
                default:
                    throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
            }
        }
        catch (IllegalArgumentException e) {
            throw new ValueFormatException("Error converting value to long", e);
        }
    }

    /**
     * @see javax.jcr.Value#getString()
     */
    @Override
    public String getString() throws RepositoryException {
        checkState(getType() != PropertyType.BINARY || stream == null,
                "getStream has previously been called on this Value instance. " +
                "In this case a new Value instance must be acquired in order to successfully call this method.");

        switch (getType()) {
            case PropertyType.NAME:
                return namePathMapper.getJcrName(getOakString());
            case PropertyType.PATH:
                String s = getOakString();
                if (s.startsWith("[") && s.endsWith("]")) {
                    // identifier paths are returned as-is (JCR 2.0, 3.4.3.1)
                    return s;
                } else {
                    return namePathMapper.getJcrPath(s);
                }
            default:
                return getOakString();
        }
    }

    /**
     * @see javax.jcr.Value#getStream()
     */
    @Override
    public InputStream getStream() throws IllegalStateException, RepositoryException {
        if (stream == null) {
            stream = getBlob().getNewStream();
        }
        return stream;
    }

    /**
     * @see javax.jcr.Value#getBinary()
     */
    @Override
    public Binary getBinary() throws RepositoryException {
        return new BinaryImpl(this);
    }

    @Override
    public String getContentIdentity() {
        try {
            return getBlob().getContentIdentity();
        } catch (RepositoryException e) {
            LOG.warn("Error getting content identity", e);
            return null;
        }
    }

    //-------------------------------------------------------------< Object >---

    /**
     * @see Object#equals(Object)
     */
    @Override
    public boolean equals(Object other) {
        if (other instanceof ValueImpl) {
            ValueImpl that = (ValueImpl) other;
            Type<?> thisType = this.type;
            if (thisType.isArray()) {
                thisType = thisType.getBaseType();
            }
            Type<?> thatType = that.type;
            if (thatType.isArray()) {
                thatType = thatType.getBaseType();
            }
            try {
                return thisType == thatType
                        && Objects.equal(
                        getValue(thatType, index),
                        that.getValue(thatType, that.index));
            } catch (RepositoryException e) {
                LOG.warn("Error while comparing values", e);
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * @see Object#hashCode()
     */
    @Override
    public int hashCode() {
        try {
            if (getType() == PropertyType.BINARY) {
                return getValue(Type.BINARY, index).hashCode();
            } else {
                return getValue(Type.STRING, index).hashCode();
            }
        } catch (RepositoryException e) {
            LOG.warn("Error while calculating hash code", e);
            return 0;
        }
    }

    @Override
    public String toString() {
        try {
            return getValue(Type.STRING, index);
        } catch (RepositoryException e) {
            return e.toString();
        }
    }

    @Nullable
    URI getDownloadURI(@NotNull Blob blob, @NotNull BinaryDownloadOptions downloadOptions) {
        if (blobAccessProvider == null) {
            return null;
        } else {
            return blobAccessProvider.getDownloadURI(blob,
                    new BlobDownloadOptions(
                            downloadOptions.getMediaType(),
                            downloadOptions.getCharacterEncoding(),
                            downloadOptions.getFileName(),
                            downloadOptions.getDispositionType())
                    );
        }
    }

    //------------------------------------------------------------< private >---

    private <T> T getValue(Type<T> type, int index) throws RepositoryException {
        try {
            return propertyState.getValue(type, index);
        } catch (IllegalRepositoryStateException e) {
            throw new RepositoryException(e);
        }
    }

    private static Type<?> getType(PropertyState property) throws RepositoryException {
        try {
            return property.getType();
        } catch (IllegalRepositoryStateException e) {
            throw new RepositoryException(e);
        }
    }

}
