/* ====================================================================
   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.poi.hpsf;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
import org.apache.poi.util.CodePageUtil;

import static org.apache.logging.log4j.util.Unbox.box;

/**
 * Maintains the instances of {@link CustomProperty} that belong to a
 * {@link DocumentSummaryInformation}. The class maintains the names of the
 * custom properties in a dictionary. It implements the {@link Map} interface
 * and by this provides a simplified view on custom properties: A property's
 * name is the key that maps to a typed value. This implementation hides
 * property IDs from the developer and regards the property names as keys to
 * typed values.<p>
 *
 * While this class provides a simple API to custom properties, it ignores
 * the fact that not names, but IDs are the real keys to properties. Under the
 * hood this class maintains a 1:1 relationship between IDs and names. Therefore
 * you should not use this class to process property sets with several IDs
 * mapping to the same name or with properties without a name: the result will
 * contain only a subset of the original properties. If you really need to deal
 * such property sets, use HPSF's low-level access methods.<p>
 *
 * An application can call the {@link #isPure} method to check whether a
 * property set parsed by {@link CustomProperties} is still pure (i.e.
 * unmodified) or whether one or more properties have been dropped.<p>
 *
 * This class is not thread-safe; concurrent access to instances of this
 * class must be synchronized.<p>
 *
 * While this class is roughly HashMap&lt;Long,CustomProperty&gt;, that's the
 * internal representation. To external calls, it should appear as
 * HashMap&lt;String,Object&gt; mapping between Names and Custom Property Values.
 */
public class CustomProperties implements Map<String,Object> {
    private static final Logger LOG = LogManager.getLogger(CustomProperties.class);

    /**
     * The custom properties
     */
    private final HashMap<Long,CustomProperty> props = new HashMap<>();
    
    /**
     * Maps property IDs to property names and vice versa.
     */
    private final TreeBidiMap<Long,String> dictionary = new TreeBidiMap<>();

    /**
     * Tells whether this object is pure or not.
     */
    private boolean isPure = true;

    private int codepage = -1;

    /**
     * Puts a {@link CustomProperty} into this map. It is assumed that the
     * {@link CustomProperty} already has a valid ID. Otherwise use
     * {@link #put(CustomProperty)}.
     * 
     * @param name the property name
     * @param cp the property
     * 
     * @return the previous property stored under this name
     */
    public CustomProperty put(final String name, final CustomProperty cp) {
        if (name == null) {
            /* Ignoring a property without a name. */
            isPure = false;
            return null;
        }
        
        if (!name.equals(cp.getName())) {
            throw new IllegalArgumentException("Parameter \"name\" (" + name +
                    ") and custom property's name (" + cp.getName() +
                    ") do not match.");
        }

        checkCodePage(name);
        
        /* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a  */
        props.remove(dictionary.getKey(name));
        dictionary.put(cp.getID(), name);

        /* Put the custom property into this map. */
        return props.put(cp.getID(), cp);
    }

    /**
     * Adds a named property.
     *
     * @param key The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         {@code null} if there was no such property before.
     */
    @Override
    public Object put(String key, Object value) {
        int variantType;
        if (value instanceof String) {
            variantType = Variant.VT_LPSTR;
        } else if (value instanceof Short) {
            variantType = Variant.VT_I2;
        } else if (value instanceof Integer) {
            variantType = Variant.VT_I4;
        } else if (value instanceof Long) {
            variantType = Variant.VT_I8;
        } else if (value instanceof Float) {
            variantType = Variant.VT_R4;
        } else if (value instanceof Double) {
            variantType = Variant.VT_R8;
        } else if (value instanceof Boolean) {
            variantType = Variant.VT_BOOL;
        } else if (value instanceof BigInteger
            && ((BigInteger)value).bitLength() <= 64
            && ((BigInteger)value).compareTo(BigInteger.ZERO) >= 0) {
            variantType = Variant.VT_UI8;
        } else if (value instanceof Date) {
            variantType = Variant.VT_FILETIME;
        } else {
            throw new IllegalStateException("unsupported datatype - currently String,Short,Integer,Long,Float,Double,Boolean,BigInteger(unsigned long),Date can be processed.");
        }
        final Property p = new Property(-1, variantType, value);
        return put(new CustomProperty(p, key));
    }
    
    /**
     * Gets a named value from the custom properties - only works for keys of type String
     *
     * @param key the name of the value to get
     * @return the value or {@code null} if a value with the specified
     *         name is not found in the custom properties.
     */
    @Override
    public Object get(final Object key) {
        final Long id = dictionary.getKey(key);
        final CustomProperty cp = props.get(id);
        return cp != null ? cp.getValue() : null;
    }

    /**
     * Removes a custom property - only works for keys of type String
     * @param key The name of the custom property to remove
     * @return The removed property or {@code null} if the specified property was not found.
     */
    @Override
    public CustomProperty remove(Object key) {
        final Long id = dictionary.removeValue(key);
        return props.remove(id);
    }

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

    @Override
    public boolean isEmpty() {
        return props.isEmpty();
    }

    @Override
    public void clear() {
        props.clear();
    }
    
    @Override
    public int hashCode() {
        return props.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof CustomProperties && props.equals(((CustomProperties) obj).props);
    }

    @Override
    public void putAll(Map<? extends String, ?> m) {
        for (Entry<? extends String, ?> me : m.entrySet()) {
            put(me.getKey(), me.getValue());
        }
    }

    /**
     * @return the list of properties
     */
    public List<CustomProperty> properties() {
        List<CustomProperty> list = new ArrayList<>(props.size());
        list.addAll(props.values());
        return Collections.unmodifiableList(list);
    }
    
    /**
     * @return the list of property values - use {@link #properties()} for the wrapped values 
     */
    @Override
    public Collection<Object> values() {
        List<Object> list = new ArrayList<>(props.size());
        for (CustomProperty property : props.values()) {
            list.add(property.getValue());
        }
        return Collections.unmodifiableCollection(list);
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        Map<String,Object> set = new LinkedHashMap<>(props.size());
        for (CustomProperty property : props.values()) {
            set.put(property.getName(), property.getValue());
        }
        return Collections.unmodifiableSet(set.entrySet());
    }

    /**
     * Returns a set of all the names of our custom properties.
     * Equivalent to {@link #nameSet()}
     * 
     * @return a set of all the names of our custom properties
     */
    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Set keySet() {
        return Collections.unmodifiableSet(dictionary.values());
    }

    /**
     * Returns a set of all the names of our custom properties
     * 
     * @return a set of all the names of our custom properties
     */
    public Set<String> nameSet() {
        return Collections.unmodifiableSet(dictionary.values());
    }

    /**
     * Returns a set of all the IDs of our custom properties
     * 
     * @return a set of all the IDs of our custom properties
     */
    public Set<Long> idSet() {
        return Collections.unmodifiableSet(dictionary.keySet());
    }


    /**
     * Sets the codepage.
     *
     * @param codepage the codepage
     */
    public void setCodepage(final int codepage) {
        this.codepage = codepage;
    }

    /**
     * Gets the codepage.
     *
     * @return the codepage or -1 if the codepage is undefined.
     */
    public int getCodepage() {
        return codepage;
    }

    /**
     * <p>Gets the dictionary which contains IDs and names of the named custom
     * properties.
     *
     * @return the dictionary.
     */
    Map<Long,String> getDictionary() {
        return dictionary;
    }


    /**
     * Checks against both String Name and Long ID
     */
    @Override
    public boolean containsKey(Object key) {
        return ((key instanceof Long && dictionary.containsKey(key)) || dictionary.containsValue(key));
    }

    /**
     * Checks against both the property, and its values. 
     */
    @Override
    public boolean containsValue(Object value) {
        if(value instanceof CustomProperty) {
            return props.containsValue(value);
        }
      
        for(CustomProperty cp : props.values()) {
            if(cp.getValue() == value) {
                return true;
            }
        }

        return false;
    }

    /**
     * Tells whether this {@link CustomProperties} instance is pure or one or
     * more properties of the underlying low-level property set has been
     * dropped.
     *
     * @return {@code true} if the {@link CustomProperties} is pure, else
     *         {@code false}.
     */
    public boolean isPure() {
        return isPure;
    }

    /**
     * Sets the purity of the custom property set.
     *
     * @param isPure the purity
     */
    public void setPure(final boolean isPure) {
        this.isPure = isPure;
    }

    /**
     * Puts a {@link CustomProperty} that has not yet a valid ID into this
     * map. The method will allocate a suitable ID for the custom property:
     *
     * <ul>
     * <li>If there is already a property with the same name, take the ID
     * of that property.
     *
     * <li>Otherwise find the highest ID and use its value plus one.
     * </ul>
     *
     * @param customProperty The {@link CustomProperty} to add.
     * @return If there was already a property with the same name, the old property
     * @throws ClassCastException
     */
    private Object put(final CustomProperty customProperty) throws ClassCastException {
        final String name = customProperty.getName();

        /* Check whether a property with this name is in the map already. */
        final Long oldId = (name == null) ? null :  dictionary.getKey(name);
        if (oldId != null) {
            customProperty.setID(oldId);
        } else {
            long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
            long nextKey = Math.max(lastKey,PropertyIDMap.PID_MAX)+1;
            customProperty.setID(nextKey);
        }
        return this.put(name, customProperty);
    }

    private void checkCodePage(String value) {
        int cp = getCodepage();
        if (cp == -1) {
            cp = Property.DEFAULT_CODEPAGE;
        }
        if (cp == CodePageUtil.CP_UNICODE) {
            return;
        }
        String cps = "";
        try {
            cps = CodePageUtil.codepageToEncoding(cp, false);
        } catch (UnsupportedEncodingException e) {
            LOG.atError().log("Codepage '{}' can't be found.", box(cp));
        }
        if (!cps.isEmpty() && Charset.forName(cps).newEncoder().canEncode(value)) {
            return;
        }
        LOG.atDebug().log("Charset '{}' can't encode '{}' - switching to unicode.", cps, value);
        setCodepage(CodePageUtil.CP_UNICODE);
    }
}
