/*
**
** Copyright (C) 2014, 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.
*/

/*
 * This class is used to create, load tables for HBPCD
 * HBPCD means 'Handset Based Plus Code Dialing', for CDMA network, most of network
 * couldn't handle international dialing number with '+', it need to be converted
 * to a IDD (International Direct Dialing) number, and some CDMA network won't
 * broadcast operator numeric, we need CDMA system ID and timezone etc. information
 * to get right MCC part of numeric, MNC part of numeric has no way to get in this
 * case, but for HBPCD, the MCC is enough.
 *
 * Table TABLE_MCC_LOOKUP_TABLE
 * This table has country name, country code, time zones for each MCC
 *
 * Table TABLE_MCC_IDD
 * This table has the IDDs for each MCC, some countries have multiple IDDs.
 *
 * Table TABLE_MCC_SID_RANGE
 * This table are SIDs assigned to each MCC
 *
 * Table TABLE_MCC_SID_CONFLICT
 * This table shows those SIDs are assigned to more than 1 MCC entry,
 * if the SID is here, it means the SID couldn't be matched to a single MCC,
 * it need to check the time zone and SID in TABLE_MCC_LOOKUP_TABLE to get
 * right MCC.
 *
 * Table TABLE_ARBITRARY_MCC_SID_MATCH
 * The SID listed in this table technically have operators in multiple MCC,
 * but conveniently only have *active* operators in a single MCC allowing a
 * unique SID->MCC lookup.  Lookup by Timezone however would be complicatedi
 * as there will be multiple matches, and those matched entries have same
 * time zone, which can not tell which MCC is right. Conventionaly it is known
 * that SID is used only by the *active* operators in that MCC.
 *
 * Table TABLE_NANP_AREA_CODE
 * This table has NANP(North America Number Planning) area code, this is used
 * to check if a dialing number is a NANP number.
 */

package com.android.providers.telephony;

import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

import com.android.internal.telephony.HbpcdLookup;
import com.android.internal.telephony.HbpcdLookup.MccIdd;
import com.android.internal.telephony.HbpcdLookup.MccLookup;
import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
import com.android.internal.telephony.HbpcdLookup.MccSidRange;
import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
import com.android.internal.util.XmlUtils;

public class HbpcdLookupDatabaseHelper extends SQLiteOpenHelper {
    private static final String TAG = "HbpcdLockupDatabaseHelper";
    private static final boolean DBG = true;

    private static final String DATABASE_NAME = "HbpcdLookup.db";
    private static final int DATABASE_VERSION = 1;
    private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;

    // Context to access resources with
    private Context mContext;

    /**
     * DatabaseHelper helper class for loading apns into a database.
     *
     * @param context of the user.
     */
    public HbpcdLookupDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);

        mContext = context;
        // Memory optimization - close idle connections after 30s of inactivity
        setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
        setWriteAheadLoggingEnabled(false);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //set up the database schema
        // 1 MCC may has more IDDs
        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_IDD +
            "(_id INTEGER PRIMARY KEY," +
                "MCC INTEGER," +
                "IDD TEXT);");

        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE +
            "(_id INTEGER PRIMARY KEY," +
                "MCC INTEGER," +
                "Country_Code TEXT," +
                "Country_Name TEXT," +
                "NDD TEXT," +
                "NANPS BOOLEAN," +
                "GMT_Offset_Low REAL," +
                "GMT_Offset_High REAL," +
                "GMT_DST_Low REAL," +
                "GMT_DST_High REAL);");

        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT +
            "(_id INTEGER PRIMARY KEY," +
                "MCC INTEGER," +
                "SID_Conflict INTEGER);");

        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_RANGE +
            "(_id INTEGER PRIMARY KEY," +
                "MCC INTEGER," +
                "SID_Range_Low INTEGER," +
                "SID_Range_High INTEGER);");

        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_NANP_AREA_CODE +
            "(_id INTEGER PRIMARY KEY," +
                "AREA_CODE INTEGER UNIQUE);");

        db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH +
            "(_id INTEGER PRIMARY KEY," +
                "MCC INTEGER," +
                "SID INTEGER UNIQUE);");

        initDatabase(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // do nothing
    }

    private void initDatabase (SQLiteDatabase db) {
        // Read internal data from xml
        Resources r = mContext.getResources();
        XmlResourceParser parser = r.getXml(R.xml.hbpcd_lookup_tables);

        if (parser == null) {
           Log.e (TAG, "error to load the HBPCD resource");
        } else {
            try {
                db.beginTransaction();
                XmlUtils.beginDocument(parser, "hbpcd_info");

                int eventType = parser.getEventType();
                String tagName = parser.getName();

                while (eventType != XmlPullParser.END_DOCUMENT) {
                    if (eventType == XmlPullParser.START_TAG
                            && tagName.equalsIgnoreCase("table")) {
                        String tableName = parser.getAttributeValue(null, "name");
                        loadTable(db, parser, tableName);
                    }
                    parser.next();
                    eventType = parser.getEventType();
                    tagName = parser.getName();
                }
                db.setTransactionSuccessful();
            } catch (XmlPullParserException e) {
                Log.e (TAG, "Got XmlPullParserException when load hbpcd info");
            } catch (IOException e) {
                Log.e (TAG, "Got IOException when load hbpcd info");
            } catch (SQLException e) {
                Log.e (TAG, "Got SQLException when load hbpcd info");
            } finally {
                db.endTransaction();
                parser.close();
            }
        }
    }

    private void loadTable(SQLiteDatabase db, XmlPullParser parser, String tableName)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        while (!(eventType == XmlPullParser.END_TAG
                && tagName.equalsIgnoreCase("table"))) {
            ContentValues row = null;
            if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_IDD)) {
                row = getTableMccIddRow(parser);
            } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE)) {
                row = getTableMccLookupTableRow(parser);
            } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT)) {
                row = getTableMccSidConflictRow(parser);
            } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_RANGE)) {
                row = getTableMccSidRangeRow(parser);
            } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_NANP_AREA_CODE)) {
                row = getTableNanpAreaCodeRow(parser);
            } else if (tableName.equalsIgnoreCase(
                    HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH)) {
                row = getTableArbitraryMccSidMatch(parser);
            } else {
                Log.e(TAG, "unrecognized table name"  + tableName);
                break;
            }
            if (row != null) {
                db.insert(tableName, null, row);
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
    }

    private ContentValues getTableMccIddRow(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(MccIdd.MCC)) {
                    row.put(MccIdd.MCC, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccIdd.IDD)) {
                    row.put(MccIdd.IDD, parser.nextText());
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
        return row;
    }

    private ContentValues getTableMccLookupTableRow(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(MccLookup.MCC)) {
                    row.put(MccLookup.MCC, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_CODE)) {
                    row.put(MccLookup.COUNTRY_CODE, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_NAME)) {
                    row.put(MccLookup.COUNTRY_NAME, parser.nextText());
                } else if (tagName.equalsIgnoreCase(MccLookup.NDD)) {
                    row.put(MccLookup.NDD, parser.nextText());
                } else if (tagName.equalsIgnoreCase(MccLookup.NANPS)) {
                    row.put(MccLookup.NANPS, Boolean.parseBoolean(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_LOW)) {
                    row.put(MccLookup.GMT_OFFSET_LOW, Float.parseFloat(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_HIGH)) {
                    row.put(MccLookup.GMT_OFFSET_HIGH, Float.parseFloat(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_LOW)) {
                    row.put(MccLookup.GMT_DST_LOW, Float.parseFloat(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_HIGH)) {
                    row.put(MccLookup.GMT_DST_HIGH, Float.parseFloat(parser.nextText()));
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
        return row;
    }

    private ContentValues getTableMccSidConflictRow(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(MccSidConflicts.MCC)) {
                    row.put(MccSidConflicts.MCC, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccSidConflicts.SID_CONFLICT)) {
                    row.put(MccSidConflicts.SID_CONFLICT, Integer.parseInt(parser.nextText()));
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
        return row;
    }

    private ContentValues getTableMccSidRangeRow(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(MccSidRange.MCC)) {
                    row.put(MccSidRange.MCC, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_LOW)) {
                    row.put(MccSidRange.RANGE_LOW, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_HIGH)) {
                    row.put(MccSidRange.RANGE_HIGH, Integer.parseInt(parser.nextText()));
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
       }
       return row;
    }

    private ContentValues getTableNanpAreaCodeRow(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(NanpAreaCode.AREA_CODE)) {
                    row.put(NanpAreaCode.AREA_CODE, Integer.parseInt(parser.nextText()));
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
        return row;
    }

    private ContentValues getTableArbitraryMccSidMatch(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName = parser.getName();
        ContentValues row = new ContentValues();

        while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
            if (eventType == XmlPullParser.START_TAG) {
                if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.MCC)) {
                    row.put(ArbitraryMccSidMatch.MCC, Integer.parseInt(parser.nextText()));
                } else if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.SID)) {
                    row.put(ArbitraryMccSidMatch.SID, Integer.parseInt(parser.nextText()));
                }
            }
            parser.next();
            eventType = parser.getEventType();
            tagName = parser.getName();
        }
        return row;
    }
}
