/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed 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 com.android.server;

import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.UserHandle;
import android.util.SparseArray;

import java.util.HashMap;
import java.util.WeakHashMap;

/**
 * TODO: This should be better integrated into the system so it doesn't need
 * special calls from the activity manager to clear it.
 */
public final class AttributeCache {
    private static AttributeCache sInstance = null;
    
    private final Context mContext;
    private final WeakHashMap<String, Package> mPackages =
            new WeakHashMap<String, Package>();
    private final Configuration mConfiguration = new Configuration();
    
    public final static class Package {
        public final Context context;
        private final SparseArray<HashMap<int[], Entry>> mMap
                = new SparseArray<HashMap<int[], Entry>>();
        
        public Package(Context c) {
            context = c;
        }
    }
    
    public final static class Entry {
        public final Context context;
        public final TypedArray array;
        
        public Entry(Context c, TypedArray ta) {
            context = c;
            array = ta;
        }
    }
    
    public static void init(Context context) {
        if (sInstance == null) {
            sInstance = new AttributeCache(context);
        }
    }
    
    public static AttributeCache instance() {
        return sInstance;
    }
    
    public AttributeCache(Context context) {
        mContext = context;
    }
    
    public void removePackage(String packageName) {
        synchronized (this) {
            mPackages.remove(packageName);
        }
    }
    
    public void updateConfiguration(Configuration config) {
        synchronized (this) {
            int changes = mConfiguration.updateFrom(config);
            if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE |
                    ActivityInfo.CONFIG_KEYBOARD_HIDDEN |
                    ActivityInfo.CONFIG_ORIENTATION)) != 0) {
                // The configurations being masked out are ones that commonly
                // change so we don't want flushing the cache... all others
                // will flush the cache.
                mPackages.clear();
            }
        }
    }
    
    public Entry get(String packageName, int resId, int[] styleable, int userId) {
        synchronized (this) {
            Package pkg = mPackages.get(packageName);
            HashMap<int[], Entry> map = null;
            Entry ent = null;
            if (pkg != null) {
                map = pkg.mMap.get(resId);
                if (map != null) {
                    ent = map.get(styleable);
                    if (ent != null) {
                        return ent;
                    }
                }
            } else {
                Context context;
                try {
                    context = mContext.createPackageContextAsUser(packageName, 0,
                            new UserHandle(userId));
                    if (context == null) {
                        return null;
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    return null;
                }
                pkg = new Package(context);
                mPackages.put(packageName, pkg);
            }
            
            if (map == null) {
                map = new HashMap<int[], Entry>();
                pkg.mMap.put(resId, map);
            }
            
            try {
                ent = new Entry(pkg.context,
                        pkg.context.obtainStyledAttributes(resId, styleable));
                map.put(styleable, ent);
            } catch (Resources.NotFoundException e) {
                return null;
            }
            
            return ent;
        }
    }
}

