/*
 * 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.chemistry.opencmis.jcr;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeType;

import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.PropertyBoolean;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.PropertyDateTime;
import org.apache.chemistry.opencmis.commons.data.PropertyDecimal;
import org.apache.chemistry.opencmis.commons.data.PropertyHtml;
import org.apache.chemistry.opencmis.commons.data.PropertyId;
import org.apache.chemistry.opencmis.commons.data.PropertyInteger;
import org.apache.chemistry.opencmis.commons.data.PropertyString;
import org.apache.chemistry.opencmis.commons.data.PropertyUri;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyData;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriImpl;
import org.apache.chemistry.opencmis.jcr.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class providing methods for converting various entities from/to their
 * respective representation in JCR/CMIS.
 */
public final class JcrConverter {

    private static final Logger log = LoggerFactory.getLogger(JcrConverter.class);
    private static final Pattern QUALIFIED_NAME = Pattern.compile("\\{([^}]*)\\}(.*)");
    private static final Pattern PREFIXED_NAME = Pattern.compile("(([^:/]+):)?([^:]*)");

    private JcrConverter() {
    }

    /**
     * Escapes all illegal for JCR local name characters of a string. The
     * encoding is loosely modeled after URI encoding, but only encodes the
     * characters it absolutely needs to in order to make the resulting string a
     * valid JCR name.
     * <p/>
     * QName EBNF:<br>
     * 
     * <pre>
     * simplename ::= onecharsimplename | twocharsimplename | threeormorecharname
     * onecharsimplename ::= (* Any Unicode character except: '.', '/', ':', '[', ']', '*', '|' or any whitespace character *)
     * twocharsimplename ::= '.' onecharsimplename | onecharsimplename '.' | onecharsimplename onecharsimplename
     * threeormorecharname ::= nonspace string nonspace
     * string ::= char | string char
     * char ::= nonspace | ' '
     * nonspace ::= (* Any Unicode character except: '/', ':', '[', ']', '*', '|' or any whitespace character *)
     * </pre>
     * 
     * @param cmisName
     *            the name to escape
     * @return the escaped name
     */
    private static String escapeForJcr(String cmisName) {
        StringBuilder buffer = new StringBuilder(cmisName.length() * 16 + 32);
        for (int i = 0; i < cmisName.length(); i++) {
            char ch = cmisName.charAt(i);
            if (ch == '%' || ch == '/' || ch == ':' || ch == '[' || ch == ']' || ch == '*' || ch == '|' || ch == '\t'
                    || ch == '\r' || ch == '\n' || ch == '.' && cmisName.length() < 3 || ch == ' '
                    && (i == 0 || i == cmisName.length() - 1)) {
                buffer.append('%');
                buffer.append(Character.toUpperCase(Character.forDigit(ch / 16, 16)));
                buffer.append(Character.toUpperCase(Character.forDigit(ch % 16, 16)));
            } else {
                buffer.append(ch);
            }
        }
        return buffer.toString();
    }

    /**
     * See JSR-283, 3.2 Names A JCR name is an ordered pair of strings: (N, L)
     * where N is a JCR namespace and L is a JCR local name.
     * 
     * @param cmisName
     *            the name to escape
     * @return the escaped name
     */
    public static String toJcrName(String cmisName) {
        if (cmisName == null || cmisName.length() == 0) {
            return null;
        }
        if (cmisName.charAt(0) == '{') {
            Matcher matcher = QUALIFIED_NAME.matcher(cmisName);
            if (matcher.matches()) {
                String namespaceUri = matcher.group(1);
                String localName = matcher.group(2);
                StringBuilder builder = new StringBuilder(cmisName.length() * 16 + 32);
                if (namespaceUri != null && namespaceUri.length() > 0) {
                    // This must be valid URI
                    try {
                        namespaceUri = new URI(namespaceUri).toString();
                        builder.append('{');
                        builder.append(namespaceUri);
                        builder.append('}');
                    } catch (URISyntaxException e1) {
                        // Skip URI
                        log.debug(e1.getMessage(), e1);
                    }
                }
                builder.append(escapeForJcr(localName));
                return builder.toString();
            }
        } else {
            Matcher matcher = PREFIXED_NAME.matcher(cmisName);
            if (matcher.matches()) {
                String prefix = matcher.group(2);
                String localName = matcher.group(3);
                StringBuilder builder = new StringBuilder(cmisName.length() * 16 + 32);
                if (prefix != null && prefix.length() > 0) {
                    builder.append(escapeForJcr(prefix));
                    builder.append(':');
                }
                builder.append(escapeForJcr(localName));
                return builder.toString();
            }
        }
        return escapeForJcr(cmisName);
    }

    /**
     * Convert a JCR <code>Property</code> to a CMIS <code>PropertyData</code>.
     * 
     * @param jcrProperty
     * @return
     * @throws RepositoryException
     */
    public static PropertyData<?> convert(Property jcrProperty) throws RepositoryException {
        AbstractPropertyData<?> propertyData;

        switch (jcrProperty.getType()) {
        case PropertyType.BINARY:
        case PropertyType.NAME:
        case PropertyType.PATH:
        case PropertyType.REFERENCE:
        case PropertyType.WEAKREFERENCE:
        case PropertyType.STRING:
            propertyData = jcrProperty.isMultiple() ? new PropertyStringImpl(jcrProperty.getName(),
                    toStrings(jcrProperty.getValues())) : new PropertyStringImpl(jcrProperty.getName(),
                    jcrProperty.getString());
            break;

        case PropertyType.LONG:
            propertyData = jcrProperty.isMultiple() ? new PropertyIntegerImpl(jcrProperty.getName(),
                    toInts(jcrProperty.getValues())) : new PropertyIntegerImpl(jcrProperty.getName(),
                    BigInteger.valueOf(jcrProperty.getLong()));
            break;

        case PropertyType.DECIMAL:
            propertyData = jcrProperty.isMultiple() ? new PropertyDecimalImpl(jcrProperty.getName(),
                    toDecs(jcrProperty.getValues())) : new PropertyDecimalImpl(jcrProperty.getName(),
                    jcrProperty.getDecimal());
            break;

        case PropertyType.DOUBLE:
            propertyData = jcrProperty.isMultiple() ? new PropertyDecimalImpl(jcrProperty.getName(),
                    doublesToDecs(jcrProperty.getValues())) : new PropertyDecimalImpl(jcrProperty.getName(),
                    BigDecimal.valueOf(jcrProperty.getDouble()));
            break;

        case PropertyType.DATE:
            propertyData = jcrProperty.isMultiple() ? new PropertyDateTimeImpl(jcrProperty.getName(),
                    toDates(jcrProperty.getValues())) : new PropertyDateTimeImpl(jcrProperty.getName(),
                    Util.toCalendar(jcrProperty.getDate()));
            break;

        case PropertyType.BOOLEAN:
            propertyData = jcrProperty.isMultiple() ? new PropertyBooleanImpl(jcrProperty.getName(),
                    toBools(jcrProperty.getValues())) : new PropertyBooleanImpl(jcrProperty.getName(),
                    jcrProperty.getBoolean());
            break;

        case PropertyType.URI:
            propertyData = jcrProperty.isMultiple() ? new PropertyUriImpl(jcrProperty.getName(),
                    toStrings(jcrProperty.getValues())) : new PropertyUriImpl(jcrProperty.getName(),
                    jcrProperty.getString());
            break;

        default:
            throw new CmisInvalidArgumentException("Invalid property type: " + jcrProperty.getType());
        }

        propertyData.setDisplayName(jcrProperty.getName());
        propertyData.setLocalName(jcrProperty.getName());
        propertyData.setQueryName(jcrProperty.getName());

        return propertyData;
    }

    /**
     * Set a property on a JCR node.
     * 
     * @param node
     *            the node to set the property
     * @param propertyData
     *            the property to set
     * @throws RepositoryException
     */
    public static void setProperty(Node node, PropertyData<?> propertyData) throws RepositoryException {
        Value[] values;
        int propertyType;

        if (propertyData instanceof PropertyBoolean) {
            values = toValue((PropertyBoolean) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.BOOLEAN;
        } else if (propertyData instanceof PropertyDateTime) {
            values = toValue((PropertyDateTime) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.DATE;
        } else if (propertyData instanceof PropertyDecimal) {
            values = toValue((PropertyDecimal) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.DECIMAL;
        } else if (propertyData instanceof PropertyHtml) {
            values = toValue((PropertyHtml) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.STRING;
        } else if (propertyData instanceof PropertyId) {
            values = toValue((PropertyId) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.STRING;
        } else if (propertyData instanceof PropertyInteger) {
            values = toValue((PropertyInteger) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.DECIMAL;
        } else if (propertyData instanceof PropertyString) {
            values = toValue((PropertyString) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.STRING;
        } else if (propertyData instanceof PropertyUri) {
            values = toValue((PropertyUri) propertyData, node.getSession().getValueFactory());
            propertyType = PropertyType.URI;
        } else {
            throw new CmisInvalidArgumentException("Invalid property type: " + propertyData);
        }

        String id = propertyData.getId();
        String name;
        if (PropertyIds.NAME.equals(id)) {
            node.addMixin(NodeType.MIX_TITLE);
            name = Property.JCR_TITLE;
        } else if (PropertyIds.CONTENT_STREAM_MIME_TYPE.equals(id)) {
            name = Property.JCR_MIMETYPE;
        } else {
            name = toJcrName(propertyData.getId());
        }

        if (values.length == 1) {
            node.setProperty(name, values[0]);
        } else {
            node.setProperty(name, values, propertyType);
        }
    }

    /**
     * Remove a property from a JCR node
     * 
     * @param node
     *            the node from which to remove the property
     * @param propertyData
     *            the property to remove
     * @throws RepositoryException
     */
    public static void removeProperty(Node node, PropertyData<?> propertyData) throws RepositoryException {
        String id = propertyData.getId();
        String name = PropertyIds.NAME.equals(id) ? Property.JCR_TITLE : toJcrName(propertyData.getId());

        if (node.hasProperty(name)) {
            node.getProperty(name).remove();
        }
    }

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

    /**
     * Convert an array of <code>Value</code>s to a list of <code>String</code>
     * s.
     */
    private static List<String> toStrings(Value[] values) throws RepositoryException {
        ArrayList<String> strings = new ArrayList<String>(values.length);

        for (Value v : values) {
            strings.add(v.getString());
        }

        return strings;
    }

    /**
     * Convert an array of <code>Value</code>s to a list of
     * <code>BigInteger</code>s.
     */
    private static List<BigInteger> toInts(Value[] values) throws RepositoryException {
        ArrayList<BigInteger> ints = new ArrayList<BigInteger>(values.length);

        for (Value v : values) {
            ints.add(BigInteger.valueOf(v.getLong()));
        }

        return ints;
    }

    /**
     * Convert an array of <code>Value</code>s to a list of
     * <code>BigDecimal</code>s.
     */
    private static List<BigDecimal> toDecs(Value[] values) throws RepositoryException {
        ArrayList<BigDecimal> decs = new ArrayList<BigDecimal>(values.length);

        for (Value v : values) {
            decs.add(v.getDecimal());
        }

        return decs;
    }

    /**
     * Convert an array of double <code>Value</code>s to a list of
     * <code>BigInteger</code>s.
     */
    private static List<BigDecimal> doublesToDecs(Value[] values) throws RepositoryException {
        ArrayList<BigDecimal> decs = new ArrayList<BigDecimal>(values.length);

        for (Value v : values) {
            decs.add(BigDecimal.valueOf(v.getDouble()));
        }

        return decs;
    }

    /**
     * Convert an array of <code>Value</code>s to a list of
     * <code>Booleans</code>s.
     */
    private static List<Boolean> toBools(Value[] values) throws RepositoryException {
        ArrayList<Boolean> bools = new ArrayList<Boolean>(values.length);

        for (Value v : values) {
            bools.add(v.getBoolean());
        }

        return bools;
    }

    /**
     * Convert an array of <code>Value</code>s to a list of
     * <code>GregorianCalendar</code>s.
     */
    private static List<GregorianCalendar> toDates(Value[] values) throws RepositoryException {
        ArrayList<GregorianCalendar> dates = new ArrayList<GregorianCalendar>(values.length);

        for (Value v : values) {
            dates.add(Util.toCalendar(v.getDate()));
        }

        return dates;
    }

    /**
     * Convert a <code>PropertyBoolean</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyBoolean propertyData, ValueFactory valueFactory) {
        List<Boolean> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (Boolean v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyDateTime</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyDateTime propertyData, ValueFactory valueFactory) {
        List<GregorianCalendar> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (GregorianCalendar v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyDecimal</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyDecimal propertyData, ValueFactory valueFactory) {
        List<BigDecimal> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (BigDecimal v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyHtml</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyHtml propertyData, ValueFactory valueFactory) {
        List<String> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (String v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyId</code> to an array of JCR <code>Values</code>.
     */
    private static Value[] toValue(PropertyId propertyData, ValueFactory valueFactory) {
        List<String> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (String v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyInteger</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyInteger propertyData, ValueFactory valueFactory) {
        List<BigInteger> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (BigInteger v : values) {
            result[k++] = valueFactory.createValue(new BigDecimal(v));
        }

        return result;
    }

    /**
     * Convert a <code>PropertyString</code> to an array of JCR
     * <code>Values</code>.
     */
    private static Value[] toValue(PropertyString propertyData, ValueFactory valueFactory) {
        List<String> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (String v : values) {
            result[k++] = valueFactory.createValue(v);
        }

        return result;
    }

    /**
     * Convert a <code>PropertyUri</code> to an array of JCR <code>Values</code>
     * .
     */
    private static Value[] toValue(PropertyUri propertyData, ValueFactory valueFactory) throws ValueFormatException {
        List<String> values = propertyData.getValues();
        if (values == null) {
            return new Value[0];
        }

        Value[] result = new Value[values.size()];
        int k = 0;
        for (String v : values) {
            result[k++] = valueFactory.createValue(v, PropertyType.URI);
        }

        return result;
    }

}
