/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package sun.management.snmp.util;

import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.mbeanserver.Util;

import java.io.Serializable;

import java.util.Comparator;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import java.util.List;
import java.util.Iterator;

import java.lang.ref.WeakReference;


/**
 * This abstract class implements a weak cache that holds table data, for
 * a table whose data is obtained from a list  where a name can be obtained
 * for each item in the list.
 * <p>This object maintains a map between an entry name and its associated
 * SnmpOid index, so that a given entry is always associated to the same
 * index.</p>
 * <p><b>NOTE: This class is not synchronized, subclasses must implement
 *          the appropriate synchronization whwn needed.</b></p>
 **/
public abstract class SnmpNamedListTableCache extends SnmpListTableCache {

    /**
     * This map associate an entry name with the SnmpOid index that's
     * been allocated for it.
     **/
    protected TreeMap names = new TreeMap();

    /**
     * The last allocate index.
     **/
    protected long last = 0;

    /**
     * true if the index has wrapped.
     **/
    boolean   wrapped = false;

    /**
     * Returns the key to use as name for the given <var>item</var>.
     * <br>This method is called by {@link #getIndex(Object,List,int,Object)}.
     * The given <var>item</var> is expected to be always associated with
     * the same name.
     * @param context The context passed to
     *        {@link #updateCachedDatas(Object,List)}.
     * @param rawDatas Raw table datas passed to
     *        {@link #updateCachedDatas(Object,List)}.
     * @param rank Rank of the given <var>item</var> in the
     *        <var>rawDatas</var> list iterator.
     * @param item The raw data object for which a key name must be determined.
     **/
    protected abstract String getKey(Object context, List rawDatas,
                                     int rank, Object item);

    /**
     * Find a new index for the entry corresponding to the
     * given <var>item</var>.
     * <br>This method is called by {@link #getIndex(Object,List,int,Object)}
     * when a new index needs to be allocated for an <var>item</var>. The
     * index returned must not be already in used.
     * @param context The context passed to
     *        {@link #updateCachedDatas(Object,List)}.
     * @param rawDatas Raw table datas passed to
     *        {@link #updateCachedDatas(Object,List)}.
     * @param rank Rank of the given <var>item</var> in the
     *        <var>rawDatas</var> list iterator.
     * @param item The raw data object for which an index must be determined.
     **/
    protected SnmpOid makeIndex(Object context, List rawDatas,
                                int rank, Object item) {

        // check we are in the limits of an unsigned32.
        if (++last > 0x00000000FFFFFFFFL) {
            // we just wrapped.
            log.debug("makeIndex", "Index wrapping...");
            last = 0;
            wrapped=true;
        }

        // If we never wrapped, we can safely return last as new index.
        if (!wrapped) return new SnmpOid(last);

        // We wrapped. We must look for an unused index.
        for (int i=1;i < 0x00000000FFFFFFFFL;i++) {
            if (++last >  0x00000000FFFFFFFFL) last = 1;
            final SnmpOid testOid = new SnmpOid(last);

            // Was this index already in use?
            if (names == null) return testOid;
            if (names.containsValue(testOid)) continue;

            // Have we just used it in a previous iteration?
            if (context == null) return testOid;
            if (((Map)context).containsValue(testOid)) continue;

            // Ok, not in use.
            return testOid;
        }
        // all indexes are in use! we're stuck.
        // // throw new IndexOutOfBoundsException("No index available.");
        // better to return null and log an error.
        return null;
    }

    /**
     * Call {@link #getKey(Object,List,int,Object)} in order to get
     * the item name. Then check whether an index was already allocated
     * for the entry by that name. If yes return it. Otherwise, call
     * {@link #makeIndex(Object,List,int,Object)} to compute a new
     * index for that entry.
     * Finally store the association between
     * the name and index in the context TreeMap.
     * @param context The context passed to
     *        {@link #updateCachedDatas(Object,List)}.
     *        It is expected to
     *        be an instance of  {@link TreeMap}.
     * @param rawDatas Raw table datas passed to
     *        {@link #updateCachedDatas(Object,List)}.
     * @param rank Rank of the given <var>item</var> in the
     *        <var>rawDatas</var> list iterator.
     * @param item The raw data object for which an index must be determined.
     **/
    protected SnmpOid getIndex(Object context, List rawDatas,
                               int rank, Object item) {
        final String key   = getKey(context,rawDatas,rank,item);
        final Object index = (names==null||key==null)?null:names.get(key);
        final SnmpOid result =
            ((index != null)?((SnmpOid)index):makeIndex(context,rawDatas,
                                                      rank,item));
        if ((context != null) && (key != null) && (result != null)) {
            Map<Object, Object> map = Util.cast(context);
            map.put(key,result);
        }
        log.debug("getIndex","key="+key+", index="+result);
        return result;
    }

    /**
     * Allocate a new {@link TreeMap} to serve as context, then
     * call {@link SnmpListTableCache#updateCachedDatas(Object,List)}, and
     * finally replace the {@link #names} TreeMap by the new allocated
     * TreeMap.
     * @param rawDatas The table datas from which the cached data will be
     *        computed.
     **/
    protected SnmpCachedData updateCachedDatas(Object context, List rawDatas) {
        TreeMap ctxt = new TreeMap();
        final SnmpCachedData result =
            super.updateCachedDatas(context,rawDatas);
        names = ctxt;
        return result;
    }


    /**
     * Load a list of raw data from which to build the cached data.
     * This method is called when nothing is found in the request
     * contextual cache.
     * @param userData The request contextual cache allocated by
     *        the {@link JvmContextFactory}.
     *
     **/
    protected abstract List   loadRawDatas(Map userData);

    /**
     *The name under which the raw data is to be found/put in
     *        the request contextual cache.
     **/
    protected abstract String getRawDatasKey();

    /**
     * Get a list of raw data from which to build the cached data.
     * Obtains a list of raw data by first looking it up in the
     * request contextual cache <var>userData</var> under the given
     * <var>key</var>. If nothing is found in the cache, calls
     * {@link #loadRawDatas(Map)} to obtain a new rawData list,
     * and cache the result in <var>userData</var> under <var>key</var>.
     * @param userData The request contextual cache allocated by
     *        the {@link JvmContextFactory}.
     * @param key The name under which the raw data is to be found/put in
     *        the request contextual cache.
     *
     **/
    protected List getRawDatas(Map<Object, Object> userData, String key) {
        List rawDatas = null;

        // Look for memory manager list in request contextual cache.
        if (userData != null)
            rawDatas = (List) userData.get(key);

        if (rawDatas == null) {
            // No list in contextual cache, get it from API
            rawDatas =  loadRawDatas(userData);


            // Put list in cache...
            if (rawDatas != null && userData != null)
                userData.put(key, rawDatas);
        }

        return rawDatas;
    }

    /**
     * Update cahed datas.
     * Obtains a {@link List} of raw datas by calling
     * {@link #getRawDatas(Map,String) getRawDatas((Map)context,getRawDatasKey())}.<br>
     * Then allocate a new {@link TreeMap} to serve as temporary map between
     * names and indexes, and call {@link #updateCachedDatas(Object,List)}
     * with that temporary map as context.<br>
     * Finally replaces the {@link #names} TreeMap by the temporary
     * TreeMap.
     * @param context The request contextual cache allocated by the
     *        {@link JvmContextFactory}.
     **/
    protected SnmpCachedData updateCachedDatas(Object context) {

        final Map<Object, Object> userData =
            (context instanceof Map)?Util.<Map<Object, Object>>cast(context):null;

        // Look for memory manager list in request contextual cache.
        final List rawDatas = getRawDatas(userData,getRawDatasKey());

        log.debug("updateCachedDatas","rawDatas.size()=" +
              ((rawDatas==null)?"<no data>":""+rawDatas.size()));

        TreeMap ctxt = new TreeMap();
        final SnmpCachedData result =
            super.updateCachedDatas(ctxt,rawDatas);
        names = ctxt;
        return result;
    }

    static final MibLogger log = new MibLogger(SnmpNamedListTableCache.class);
}
