/*
 * 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.testing.mock.jcr;

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

import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;

import org.apache.jackrabbit.value.BinaryValue;

/**
 * Mock {@link Property} implementation
 */
class MockProperty extends AbstractItem implements Property {

    public MockProperty(final ItemData itemData, final Session session) {
        super(itemData, session);
        if (this.itemData.getValues() == null) {
            try {
                this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue("") });
            }
            catch (RepositoryException ex) {
                throw new RuntimeException("Initializing property failed.", ex);
            }
        }
    }

    private Value internalGetValue() throws RepositoryException {
        if (this.itemData.isMultiple()) {
            throw new ValueFormatException(this
                    + " is a multi-valued property, so it's values can only be retrieved as an array");
        } else {
            return this.itemData.getValues()[0];
        }
    }

    @Override
    public Value getValue() throws RepositoryException {
        return internalGetValue();
    }

    @Override
    public Value[] getValues() throws RepositoryException {
        if (!this.itemData.isMultiple()) {
            throw new ValueFormatException("Property is single-valued.");
        }
        Value[] valuesCopy = new Value[this.itemData.getValues().length];
        for (int i = 0; i < this.itemData.getValues().length; i++) {
            valuesCopy[i] = this.itemData.getValues()[i];
        }
        return valuesCopy;
    }

    @Override
    public void setValue(final Value newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { newValue });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final Value[] newValues) throws RepositoryException {
        if (removePropertyIfValueNull(newValues)) {
            return;
        }
        Value[] values = new Value[newValues.length];
        for (int i = 0; i < newValues.length; i++) {
            values[i] = newValues[i];
        }
        this.itemData.setValues(values);
        this.itemData.setMultiple(true);
    }

    @Override
    public void setValue(final String newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final String[] newValues) throws RepositoryException {
        if (removePropertyIfValueNull(newValues)) {
            return;
        }
        Value[] values = new Value[newValues.length];
        for (int i = 0; i < newValues.length; i++) {
            values[i] = getSession().getValueFactory().createValue(newValues[i]);
        }
        this.itemData.setValues(values);
        this.itemData.setMultiple(true);
    }

    @Override
    public void setValue(final InputStream newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { new BinaryValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final long newValue) throws RepositoryException {
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final double newValue) throws RepositoryException {
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final Calendar newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final boolean newValue) throws RepositoryException {
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final Node newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final Binary newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { new BinaryValue(newValue) });
        this.itemData.setMultiple(false);
    }

    @Override
    public void setValue(final BigDecimal newValue) throws RepositoryException {
        if (removePropertyIfValueNull(newValue)) {
            return;
        }
        this.itemData.setValues(new Value[] { getSession().getValueFactory().createValue(newValue) });
        this.itemData.setMultiple(false);
    }

    /**
     * Removes the current property (itself) if the given value is null.
     * @param value Value to check
     * @return true if property was removed
     * @throws RepositoryException
     */
    private boolean removePropertyIfValueNull(Object value) throws RepositoryException {
        if (value == null) {
            remove();
            return true;
        }
        return false;
    }

    @Override
    public boolean getBoolean() throws RepositoryException {
        return internalGetValue().getBoolean();
    }

    @Override
    public Calendar getDate() throws RepositoryException {
        return internalGetValue().getDate();
    }

    @Override
    public double getDouble() throws RepositoryException {
        return internalGetValue().getDouble();
    }

    @Override
    public long getLong() throws RepositoryException {
        return internalGetValue().getLong();
    }

    @Override
    public String getString() throws RepositoryException {
        return internalGetValue().getString();
    }

    @Override
    @SuppressWarnings("deprecation")
    public InputStream getStream() throws RepositoryException {
        return internalGetValue().getStream();
    }

    @Override
    public Binary getBinary() throws RepositoryException {
        return internalGetValue().getBinary();
    }

    @Override
    public BigDecimal getDecimal() throws RepositoryException {
        return internalGetValue().getDecimal();
    }

    @Override
    public int getType() throws RepositoryException {
        if (this.itemData.getValues().length > 0) {
            return this.itemData.getValues()[0].getType();
        }
        else {
            return PropertyType.UNDEFINED;
        }
    }

    @Override
    public long getLength() throws RepositoryException {
        return getValue().getString().length();
    }

    @Override
    public long[] getLengths() throws RepositoryException {
        if (!this.itemData.isMultiple()) {
            throw new ValueFormatException("Property is single-valued.");
        }
        long[] lengths = new long[this.itemData.getValues().length];
        for (int i = 0; i < this.itemData.getValues().length; i++) {
            lengths[i] = this.itemData.getValues()[i].getString().length();
        }
        return lengths;
    }

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

    @Override
    public boolean isMultiple() throws RepositoryException {
        return this.itemData.isMultiple();
    }

    @Override
    public PropertyDefinition getDefinition() throws RepositoryException {
        return new MockPropertyDefinition();
    }

    @Override
    public int hashCode() {
        return itemData.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof MockProperty) {
            return itemData.equals(((MockProperty)obj).itemData);
        }
        return false;
    }

    // --- unsupported operations ---
    @Override
    public Node getNode() throws RepositoryException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Property getProperty() throws RepositoryException {
        throw new UnsupportedOperationException();
    }

    private final class MockPropertyDefinition implements PropertyDefinition {

        @Override
        public boolean isMultiple() {
            return MockProperty.this.itemData.isMultiple();
        }

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

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

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

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

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

        // --- unsupported operations ---
        @Override
        public Value[] getDefaultValues() {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getRequiredType() {
            throw new UnsupportedOperationException();
        }

        @Override
        public String[] getValueConstraints() {
            throw new UnsupportedOperationException();
        }

        @Override
        public NodeType getDeclaringNodeType() {
            throw new UnsupportedOperationException();
        }

        @Override
        public String getName() {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getOnParentVersion() {
            throw new UnsupportedOperationException();
        }

        @Override
        public String[] getAvailableQueryOperators() {
            throw new UnsupportedOperationException();
        }

    }

}
