/*
 * Copyright (C) 2019 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.car.setupwizardlib.partner;

import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import java.util.EnumMap;

/** The helper reads and caches the partner configurations from Car Setup Wizard. */
public class PartnerConfigHelper {

    private static final String TAG = PartnerConfigHelper.class.getSimpleName();

    @VisibleForTesting
    static final String SUW_AUTHORITY = "com.google.android.car.setupwizard.partner";

    @VisibleForTesting
    static final String SUW_GET_PARTNER_CONFIG_METHOD = "getOverlayConfig";
    private static volatile PartnerConfigHelper sInstance = null;

    @VisibleForTesting Bundle mResultBundle = null;

    @VisibleForTesting
    final EnumMap<PartnerConfig, Object> mPartnerResourceCache = new EnumMap<>(PartnerConfig.class);

    /** Factory method to get an instance */
    public static PartnerConfigHelper get(@NonNull Context context) {
        if (sInstance == null) {
            synchronized (PartnerConfigHelper.class) {
                if (sInstance == null) {
                    sInstance = new PartnerConfigHelper(context);
                }
            }
        }
        return sInstance;
    }

    /**
     * Returns the color of given {@code partnerConfig}, or 0 if the given {@code partnerConfig}
     * is not found. If the {@code ResourceType} of the given {@code partnerConfig} is not color,
     * IllegalArgumentException will be thrown.
     *
     * @param context The context of client activity
     * @param partnerConfig The {@code PartnerConfig} of target resource
     */
    @ColorInt
    public int getColor(@NonNull Context context, PartnerConfig partnerConfig) {
        if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.COLOR) {
            throw new IllegalArgumentException("Not a color resource");
        }

        if (mPartnerResourceCache.containsKey(partnerConfig)) {
            return (int) mPartnerResourceCache.get(partnerConfig);
        }

        int result = 0;
        try {
            String resourceName = partnerConfig.getResourceName();
            ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
            if (resourceEntry == null) {
                Log.w(TAG, "Resource not found: " + resourceName);
                return 0;
            }

            Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
            result = resource.getColor(resourceEntry.getResourceId(), null);
            mPartnerResourceCache.put(partnerConfig, result);
        } catch (PackageManager.NameNotFoundException exception) {
            Log.e(TAG, exception.getMessage());
        }
        return result;
    }

    /**
     * Returns the {@code Drawable} of given {@code partnerConfig}, or {@code null} if the given
     * {@code partnerConfig} is not found. If the {@code ResourceType} of the given {@code
     * resourceConfig} is not drawable, IllegalArgumentException will be thrown.
     *
     * @param context The context of client activity
     * @param partnerConfig The {@code PartnerConfig} of target resource
     */
    @Nullable
    public Drawable getDrawable(@NonNull Context context, PartnerConfig partnerConfig) {
        if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.DRAWABLE) {
            throw new IllegalArgumentException("Not a drawable resource");
        }

        if (mPartnerResourceCache.containsKey(partnerConfig)) {
            return (Drawable) mPartnerResourceCache.get(partnerConfig);
        }

        Drawable result = null;
        try {
            String resourceName = partnerConfig.getResourceName();
            ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
            if (resourceEntry == null) {
                Log.w(TAG, "Resource not found: " + resourceName);
                return null;
            }
            Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());

            // for @null
            TypedValue outValue = new TypedValue();
            resource.getValue(resourceEntry.getResourceId(), outValue, true);
            if (outValue.type == TypedValue.TYPE_REFERENCE && outValue.data == 0) {
                return result;
            }

            result = resource.getDrawable(resourceEntry.getResourceId(), null);
            mPartnerResourceCache.put(partnerConfig, result);
        } catch (PackageManager.NameNotFoundException | NotFoundException exception) {
            Log.e(TAG, exception.getMessage());
        }
        return result;
    }

    /**
     * Returns the string of the given {@code partnerConfig}, or {@code null} if the given {@code
     * resourceConfig} is not found. If the {@code ResourceType} of the given {@code partnerConfig}
     * is not string, IllegalArgumentException will be thrown.
     *
     * @param context The context of client activity
     * @param partnerConfig The {@code PartnerConfig} of target resource
     */
    @Nullable
    public String getString(@NonNull Context context, PartnerConfig partnerConfig) {
        if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.STRING) {
            throw new IllegalArgumentException("Not a string resource");
        }

        if (mPartnerResourceCache.containsKey(partnerConfig)) {
            return (String) mPartnerResourceCache.get(partnerConfig);
        }

        String result = null;
        try {
            String resourceName = partnerConfig.getResourceName();
            ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
            if (resourceEntry == null) {
                Log.w(TAG, "Resource not found: " + resourceName);
                return null;
            }
            Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
            result = resource.getString(resourceEntry.getResourceId());
            mPartnerResourceCache.put(partnerConfig, result);
        } catch (PackageManager.NameNotFoundException exception) {
            Log.e(TAG, exception.getMessage());
        }
        return result;
    }

    /**
     * Returns the dimension of given {@code partnerConfig}. The default return value is 0.
     *
     * @param context The context of client activity
     * @param resourceConfig The {@code PartnerConfig} of target resource
     */
    public float getDimension(@NonNull Context context, PartnerConfig resourceConfig) {
        return getDimension(context, resourceConfig, 0);
    }

    /**
     * Returns the dimension of given {@code partnerConfig}. If the given {@code partnerConfig}
     * not found, will return {@code defaultValue}. If the {@code ResourceType} of given {@code
     * resourceConfig} is not dimension, will throw IllegalArgumentException.
     *
     * @param context The context of client activity
     * @param partnerConfig The {@code PartnerConfig} of target resource
     * @param defaultValue The default value
     */
    public float getDimension(
            @NonNull Context context, PartnerConfig partnerConfig, float defaultValue) {
        if (partnerConfig.getResourceType() != PartnerConfig.ResourceType.DIMENSION) {
            throw new IllegalArgumentException("Not a dimension resource");
        }

        if (mPartnerResourceCache.containsKey(partnerConfig)) {
            return (float) mPartnerResourceCache.get(partnerConfig);
        }

        float result = defaultValue;
        try {
            String resourceName = partnerConfig.getResourceName();
            ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
            if (resourceEntry == null) {
                Log.w(TAG, "Resource not found: " + resourceName);
                return defaultValue;
            }
            Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
            result = resource.getDimension(resourceEntry.getResourceId());
            mPartnerResourceCache.put(partnerConfig, result);
        } catch (PackageManager.NameNotFoundException exception) {
            Log.e(TAG, exception.getMessage());
        }
        return result;
    }

    private void getPartnerConfigBundle(Context context) {
        if (mResultBundle == null) {
            try {
                Uri contentUri =
                        new Uri.Builder()
                                .scheme(ContentResolver.SCHEME_CONTENT)
                                .authority(SUW_AUTHORITY)
                                .appendPath(SUW_GET_PARTNER_CONFIG_METHOD)
                                .build();
                mResultBundle = context.getContentResolver().call(
                        contentUri,
                        SUW_GET_PARTNER_CONFIG_METHOD,
                        /* arg= */ null,
                        /* extras= */ null);
                mPartnerResourceCache.clear();
            } catch (IllegalArgumentException exception) {
                Log.w(TAG, "Fail to get config from suw provider");
            }
        }
    }

    private Resources getResourcesByPackageName(Context context, String packageName)
            throws PackageManager.NameNotFoundException {
        PackageManager manager = context.getPackageManager();
        return manager.getResourcesForApplication(packageName);
    }

    private ResourceEntry getResourceEntryFromKey(String resourceName) {
        if (mResultBundle == null) {
            return null;
        }
        return ResourceEntry.fromBundle(mResultBundle.getBundle(resourceName));
    }

    private PartnerConfigHelper(Context context) {
        getPartnerConfigBundle(context);
    }


    @VisibleForTesting
    static synchronized void resetForTesting() {
        sInstance = null;
    }
}
