/*
 * 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.empire.jsf2.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Hashtable;
import java.util.Locale;

import org.apache.empire.commons.DateUtils;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.db.DBRowSet;
import org.apache.empire.exceptions.InternalException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jsf2.pages.PageDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class manages request parameters in a way that they cannot be analyzed and modified by the user 
 * @author doebele
 *
 */
public class ParameterMap // *Deprecated* implements Serializable
{
    // *Deprecated* private static final long serialVersionUID = 1L;

    private static final Logger           log              = LoggerFactory.getLogger(ParameterMap.class);

    private static final SimpleDateFormat dateFormat       = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss", Locale.GERMAN);
    
    static private MessageDigest          md5              = null;
    {
        try
        {
            ParameterMap.md5 = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e)
        {
            ParameterMap.log.error("MessageDigest NoSuchAlgorithmException.", e);
            throw new InternalException(e);
        }
    }
    
    private final byte[] salt;

    protected Hashtable<String, String> codeMap = new Hashtable<String, String>();

    protected final Hashtable<String, Hashtable<String, Object>> typeMap = new Hashtable<String, Hashtable<String, Object>>();
    
    public ParameterMap()
    {
        String dateTime = dateFormat.format(DateUtils.getTimeNow());
        salt = dateTime.getBytes();
    }
    
    public synchronized String encodeString(String valueAsString)
    {
        if (valueAsString==null)
            throw new InvalidArgumentException("valueAsString", valueAsString);
        // log
        if (log.isTraceEnabled())
            log.trace("Generating code for value {}.", valueAsString);
        // generate code
        md5.reset();
        if (salt!=null)
            md5.update(salt);
        md5.update(valueAsString.getBytes());
        byte s[] = ParameterMap.md5.digest();
        StringBuilder hash = new StringBuilder(32);
        for (int i = 0; i < s.length; i++)
        {   // add the hash part
            // String check = Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);;
            String part = Integer.toHexString(0x000000ff & s[i]);
            switch(part.length())
            {
                case 1: hash.append('0');
                case 2: hash.append(part);
                        break;
                default:
                        throw new UnexpectedReturnValueException(part, "Integer.toHexString");
                        // hash.append(part.substring(2));
            }
        }
        return hash.toString();
    }

    public String encodeStringWithCache(String valueAsString)
    {
        String code = codeMap.get(valueAsString);
        if (code==null)
        {   // generate code
            code = encodeString(valueAsString);
            codeMap.put(valueAsString, code);
        }
        return code;
    }

    /**
     * gets a unique name for a given rowset  
     * @param rowset
     * @return a unique name for the given rowset
     */
    protected String getRowSetTypeName(DBRowSet rowset)
    {
        /*
         * alternatively use:
         *     rowset.getName();
         * or
         *     rowset.getFullName();
         */
        return rowset.getClass().getName();
    }

    /**
     * puts an object into the parameter map
     * @param typeName
     * @param id
     * @param value
     */
    protected void putValue(String typeName, String encodedId, Object item)
    {   // put in Table
        if (encodedId==null)
        {
            throw new InvalidArgumentException("encodedId", encodedId);
        }
        Hashtable<String, Object> map = typeMap.get(typeName);
        if (map==null)
        {   map = new Hashtable<String, Object>(1);
            typeMap.put(typeName, map);
        }
        map.put(encodedId, item);
    }
    
    /**
     * encodes the objectKey and stores the item in the parameter map
     * @param typeName
     * @param id
     * @param value
     */
    protected String encodeAndStore(String typeName, String objectKey, Object item, boolean useCache)
    {   // Generate the id
        String encodedId = (useCache ? encodeStringWithCache(objectKey) : encodeString(objectKey));
        // store
        putValue(typeName, encodedId, item);
        // return id
        return encodedId;
    }

    public String put(String type, String key, boolean useCache)
    {
        // Generate id and put in map
        return encodeAndStore(type, key, key, useCache);
    }

    /**
     * Puts an object into the paramter map that implements the ParameterObject interface  
     * @param paramObject
     * @return
     */
    public String put(ParameterObject paramObject)
    {
        String objectKey;
        // check param
        if (paramObject==null || StringUtils.isEmpty((objectKey=paramObject.getObjectKey())))
            throw new InvalidArgumentException("paramObject", paramObject);
        // Generate id and put in map
        String type = paramObject.getClass().getName();
        return encodeAndStore(type, objectKey, paramObject, false);
    }

    public String put(DBRowSet rowset, Object[] key)
    {
        // Generate id and put in map
        String rowKey = StringUtils.valueOf(key);
        String type = getRowSetTypeName(rowset);
        return encodeAndStore(type, rowKey, key, false);
    }

    /*
     * do we really need this?
     * 
    public String put(Class<? extends Object> c, Object[] key)
    {
        // Generate id and put in map
        String ref = StringUtils.valueOf(key);
        String type = c.getName();
        return encodeAndStore(type, ref, key, false);
    }
    */
    
    /**
     * Generates an idParam which is only valid for the given page.
     * @param targetPage
     * @param rowset
     * @param key
     * @return
     */
    public String put(PageDefinition targetPage, DBRowSet rowset, Object[] key) {
        // Generate id and put in map
        String ref  = StringUtils.valueOf(key);
        String type = targetPage.getPageBeanName() + "$" + getRowSetTypeName(rowset);
        return encodeAndStore(type, ref, key, false);
    }

    /**
     * Gets an object from the parameter map for a given type and id
     * @param type the object type (typically the class name)
     * @param id the encoded idParam
     * @return the object
     */
    public Object get(String type, String id)
    {
        Hashtable<String, Object> map = typeMap.get(type);
        return (map!=null ? map.get(id) : null);
    }

    public void clear(String type)
    {
        Hashtable<String, Object> map = typeMap.get(type);
        if (map!=null)
            map.clear();
    }

    /**
     * Puts an object into the paramter map that implements the ParameterObject interface  
     * @param paramType
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T extends ParameterObject> T get(Class<T> paramType, String id)
    {
        String type = paramType.getName();
        Hashtable<String, Object> map = typeMap.get(type);
        return (T)(map!=null ? map.get(id) : null);
    }

    public void clear(Class<? extends ParameterObject> paramType)
    {
        String type = paramType.getName();
        clear(type);
    }

    /*
     * do we really need this?
     * 
    public Object[] getKey(Class<? extends Object> c, String id)
    {
        String type = c.getName();
        Hashtable<String, Object> map = typeMap.get(type);
        return (map!=null ? ((Object[])map.get(id)) : null);
    }
    */

    public Object[] getKey(DBRowSet rowset, String id)
    {
        String type = getRowSetTypeName(rowset);
        Hashtable<String, Object> map = typeMap.get(type);
        return (map!=null ? ((Object[])map.get(id)) : null);
    }

    public void clear(DBRowSet rowset)
    {
        String type = getRowSetTypeName(rowset);
        clear(type);
    }

    /**
     * returns an record key for a given page
     * @param page
     * @param rowset
     * @param id
     * @return
     */
    public Object[] getKey(PageDefinition page, DBRowSet rowset, String id)
    {
        String type = page.getPageBeanName() + "$" + getRowSetTypeName(rowset);
        Hashtable<String, Object> map = typeMap.get(type);
        return (map!=null ? ((Object[])map.get(id)) : null);
    }
}
