/* ====================================================================
   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.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.poi.hpsf.wellknown.PropertyIDMap;

/**
 * <p>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>
 *
 * <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>
 *
 * <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>
 *
 * <p>This class is not thread-safe; concurrent access to instances of this
 * class must be synchronized.</p>
 *
 * <p>While this class is roughly HashMap<Long,CustomProperty>, that's the
 *  internal representation. To external calls, it should appear as
 *  HashMap<String,Object> mapping between Names and Custom Property Values.</p>
 *
 * @author Rainer Klute <a
 *         href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
 */
@SuppressWarnings("serial")
public class CustomProperties extends HashMap<Object,CustomProperty>
{

    /**
     * <p>Maps property IDs to property names.</p>
     */
    private Map<Long,String> dictionaryIDToName = new HashMap<Long,String>();

    /**
     * <p>Maps property names to property IDs.</p>
     */
    private Map<String,Long> dictionaryNameToID = new HashMap<String,Long>();

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


    /**
     * <p>Puts a {@link CustomProperty} into this map. It is assumed that the
     * {@link CustomProperty} already has a valid ID. Otherwise use
     * {@link #put(CustomProperty)}.</p>
     */
    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.");

        /* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a  */
        final Long idKey = Long.valueOf(cp.getID());
        final Long oldID = dictionaryNameToID.get(name);
        dictionaryIDToName.remove(oldID);
        dictionaryNameToID.put(name, idKey);
        dictionaryIDToName.put(idKey, name);

        /* Put the custom property into this map. */
        final CustomProperty oldCp = super.remove(oldID);
        super.put(idKey, cp);
        return oldCp;
    }



    /**
     * <p>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:</p>
     *
     * <ul>
     *
     * <li><p>If there is already a property with the same name, take the ID
     * of that property.</p></li>
     *
     * <li><p>Otherwise find the highest ID and use its value plus one.</p></li>
     *
     * </ul>
     *
     * @param customProperty
     * @return If the was already a property with the same name, the
     * @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 = (Long) dictionaryNameToID.get(name);
        if (oldId != null)
            customProperty.setID(oldId.longValue());
        else
        {
            long max = 1;
            for (final Iterator<Long> i = dictionaryIDToName.keySet().iterator(); i.hasNext();)
            {
                final long id = i.next().longValue();
                if (id > max)
                    max = id;
            }
            customProperty.setID(max + 1);
        }
        return this.put(name, customProperty);
    }



    /**
     * <p>Removes a custom property.</p>
     * @param name The name of the custom property to remove
     * @return The removed property or <code>null</code> if the specified property was not found.
     *
     * @see java.util.HashSet#remove(java.lang.Object)
     */
    public Object remove(final String name)
    {
        final Long id = (Long) dictionaryNameToID.get(name);
        if (id == null)
            return null;
        dictionaryIDToName.remove(id);
        dictionaryNameToID.remove(name);
        return super.remove(id);
    }

    /**
     * <p>Adds a named string property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final String value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_LPWSTR);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }

    /**
     * <p>Adds a named long property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final Long value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_I8);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }

    /**
     * <p>Adds a named double property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final Double value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_R8);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }

    /**
     * <p>Adds a named integer property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final Integer value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_I4);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }

    /**
     * <p>Adds a named boolean property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final Boolean value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_BOOL);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }


    /**
     * <p>Gets a named value from the custom properties.</p>
     *
     * @param name the name of the value to get
     * @return the value or <code>null</code> if a value with the specified
     *         name is not found in the custom properties.
     */
    public Object get(final String name)
    {
        final Long id = (Long) dictionaryNameToID.get(name);
        final CustomProperty cp = (CustomProperty) super.get(id);
        return cp != null ? cp.getValue() : null;
    }



    /**
     * <p>Adds a named date property.</p>
     *
     * @param name The property's name.
     * @param value The property's value.
     * @return the property that was stored under the specified name before, or
     *         <code>null</code> if there was no such property before.
     */
    public Object put(final String name, final Date value)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(-1);
        p.setType(Variant.VT_FILETIME);
        p.setValue(value);
        final CustomProperty cp = new CustomProperty(p, name);
        return put(cp);
    }

    /**
     * Returns a set of all the names of our
     *  custom properties. Equivalent to 
     *  {@link #nameSet()}
     */
    public Set keySet() {
        return dictionaryNameToID.keySet();
    }

    /**
     * Returns a set of all the names of our
     *  custom properties
     */
    public Set<String> nameSet() {
        return dictionaryNameToID.keySet();
    }

    /**
     * Returns a set of all the IDs of our
     *  custom properties
     */
    public Set<String> idSet() {
        return dictionaryNameToID.keySet();
    }


    /**
     * <p>Sets the codepage.</p>
     *
     * @param codepage the codepage
     */
    public void setCodepage(final int codepage)
    {
        final MutableProperty p = new MutableProperty();
        p.setID(PropertyIDMap.PID_CODEPAGE);
        p.setType(Variant.VT_I2);
        p.setValue(Integer.valueOf(codepage));
        put(new CustomProperty(p));
    }



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


    /**
     * Checks against both String Name and Long ID
     */
   public boolean containsKey(Object key) {
      if(key instanceof Long) {
         return super.containsKey((Long)key);
      }
      if(key instanceof String) {
         return super.containsKey((Long)dictionaryNameToID.get(key));
      }
      return false;
   }

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



   /**
     * <p>Gets the codepage.</p>
     *
     * @return the codepage or -1 if the codepage is undefined.
     */
    public int getCodepage()
    {
        int codepage = -1;
        for (final Iterator<CustomProperty> i = this.values().iterator(); codepage == -1 && i.hasNext();)
        {
            final CustomProperty cp = i.next();
            if (cp.getID() == PropertyIDMap.PID_CODEPAGE)
                codepage = ((Integer) cp.getValue()).intValue();
        }
        return codepage;
    }



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

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