/*
 * Copyright (C) 2016 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.stk;

import android.content.Context;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.cat.CatLog;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.XmlUtils;

import java.util.ArrayList;

/**
 * Provides preset label and/or icon in accordance with mcc/mnc
 * conbination of the inserted SIM card for Multi-SIM model.
 */
public class StkMenuConfig {
    private static final String LOG_TAG = StkMenuConfig.class.getSimpleName();
    private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE;

    private static final String XML_OPERATORS_TAG = "operators";
    private static final String XML_OPERATOR_TAG = "operator";

    private static final String XML_MCC_ATTR = "mcc";
    private static final String XML_MNC_ATTR = "mnc";
    private static final String XML_LABEL_ATTR = "label";
    private static final String XML_ICON_ATTR = "icon";
    private static final String RESOURCE_TYPE = "drawable";

    private static final int UNSPECIFIED = -1;

    private static final Config NO_CONFIG = new Config(0, 0, null, null);

    private static final Object sLock = new Object();
    private static StkMenuConfig sInstance;

    private Context mContext;
    private ArrayList<Config> mArray;
    private Config mConfigs[] = null;

    private static class Config {
        public int mcc;
        public int mnc;
        public String label;
        public String icon;

        public Config(int mcc, int mnc, String label, String icon) {
            this.mcc = mcc;
            this.mnc = mnc;
            this.label = label;
            this.icon = icon;
        }
    }

    public static StkMenuConfig getInstance(Context applicationContext) {
        synchronized (sLock) {
            if (sInstance == null) {
                sInstance = new StkMenuConfig();
                sInstance.initialize(applicationContext);
            }
            return sInstance;
        }
    }

    /**
     * Returns a preset label, if exists.
     */
    public String getLabel(int slotId) {
        findConfig(slotId);

        if (DBG) CatLog.d(LOG_TAG, "getLabel: " + mConfigs[slotId].label + ", slot id: " + slotId);
        return mConfigs[slotId].label;
    }

    /**
     * Returns a preset icon, if exists.
     */
    public Bitmap getIcon(int slotId) {
        findConfig(slotId);

        Bitmap bitmap = null;
        if (mConfigs[slotId].icon != null) {
            int resId = mContext.getResources().getIdentifier(mConfigs[slotId].icon,
                    RESOURCE_TYPE, mContext.getPackageName());
            bitmap = resId == UNSPECIFIED ? null :
                    BitmapFactory.decodeResource(mContext.getResources(), resId);
        }
        if (DBG) CatLog.d(LOG_TAG, "getIcon: " + mConfigs[slotId].icon + ", slot id: " + slotId);
        return bitmap;
    }

    private void findConfig(int slotId) {
        SubscriptionManager sm = (SubscriptionManager) mContext.getSystemService(
                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        SubscriptionInfo info = (sm != null) ? sm.getActiveSubscriptionInfoForSimSlotIndex(slotId)
                : null;
        if (info == null) {
            mConfigs[slotId] = NO_CONFIG;
            return;
        }

        TelephonyManager telephony =
                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        String operator = telephony.getSimOperator(info.getSubscriptionId());
        if (TextUtils.isEmpty(operator) || (operator.length() < 5)) {
            mConfigs[slotId] = NO_CONFIG;
            return;
        }

        int mcc = Integer.parseInt(operator.substring(0, 3));
        int mnc = Integer.parseInt(operator.substring(3));

        if (mConfigs[slotId] != null && mConfigs[slotId].mcc == mcc
                && mConfigs[slotId].mnc == mnc) {
            if (DBG) CatLog.d(LOG_TAG, "Return the cached config, slot id: " + slotId);
            return;
        }

        if (DBG) CatLog.d(LOG_TAG, "Find config and create the cached config, slot id: " + slotId);
        for (Config config : mArray) {
            if ((config.mcc == mcc) && (config.mnc == mnc)) {
                mConfigs[slotId] = config;
                return;
            }
        }

        mConfigs[slotId] = new Config(mcc, mnc, null, null);
    }

    private void initialize(Context context) {
        mContext = context;
        mArray = new ArrayList<Config>();
        mConfigs = new Config[TelephonyManager.from(mContext).getSupportedModemCount()];

        XmlResourceParser parser = mContext.getResources().getXml(R.xml.menu_conf);

        try {
            XmlUtils.beginDocument(parser, XML_OPERATORS_TAG);

            do {
                XmlUtils.nextElement(parser);

                if (!XML_OPERATOR_TAG.equals(parser.getName())) {
                    break;
                }

                int mcc = parser.getAttributeIntValue(null, XML_MCC_ATTR, UNSPECIFIED);
                int mnc = parser.getAttributeIntValue(null, XML_MNC_ATTR, UNSPECIFIED);

                if ((mcc == UNSPECIFIED) || (mnc == UNSPECIFIED)) {
                    continue;
                }

                String label = parser.getAttributeValue(null, XML_LABEL_ATTR);
                String icon = parser.getAttributeValue(null, XML_ICON_ATTR);

                Config config = new Config(mcc, mnc, label, icon);
                mArray.add(config);
            } while (true);
        } catch (Exception e) {
            CatLog.e(LOG_TAG, "Something wrong happened while interpreting the xml file" + e);
        } finally {
            parser.close();
        }
    }
}
