/*
 * Copyright (C) 2015 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.providers.contacts;

import android.text.TextUtils;
import com.android.providers.contacts.util.NeededForTesting;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

@NeededForTesting
public class MetadataEntryParser {

    private final static String UNIQUE_CONTACT_ID = "unique_contact_id";
    private final static String ACCOUNT_TYPE = "account_type";
    private final static String CUSTOM_ACCOUNT_TYPE = "custom_account_type";
    private final static String ENUM_VALUE_FOR_GOOGLE_ACCOUNT = "GOOGLE_ACCOUNT";
    private final static String GOOGLE_ACCOUNT_TYPE = "com.google";
    private final static String ENUM_VALUE_FOR_CUSTOM_ACCOUNT = "CUSTOM_ACCOUNT";
    private final static String ACCOUNT_NAME = "account_name";
    private final static String DATA_SET = "data_set";
    private final static String ENUM_FOR_PLUS_DATA_SET = "GOOGLE_PLUS";
    private final static String ENUM_FOR_CUSTOM_DATA_SET = "CUSTOM";
    private final static String PLUS_DATA_SET_TYPE = "plus";
    private final static String CUSTOM_DATA_SET = "custom_data_set";
    private final static String CONTACT_ID = "contact_id";
    private final static String CONTACT_PREFS = "contact_prefs";
    private final static String SEND_TO_VOICEMAIL = "send_to_voicemail";
    private final static String STARRED = "starred";
    private final static String PINNED = "pinned";
    private final static String AGGREGATION_DATA = "aggregation_data";
    private final static String CONTACT_IDS = "contact_ids";
    private final static String TYPE = "type";
    private final static String FIELD_DATA = "field_data";
    private final static String FIELD_DATA_ID = "field_data_id";
    private final static String FIELD_DATA_PREFS = "field_data_prefs";
    private final static String IS_PRIMARY = "is_primary";
    private final static String IS_SUPER_PRIMARY = "is_super_primary";
    private final static String USAGE_STATS = "usage_stats";
    private final static String USAGE_TYPE = "usage_type";
    private final static String LAST_TIME_USED = "last_time_used";
    private final static String USAGE_COUNT = "usage_count";

    @NeededForTesting
    public static class UsageStats {
        @NeededForTesting
        final String mUsageType;
        @NeededForTesting
        final long mLastTimeUsed;
        @NeededForTesting
        final int mTimesUsed;

        @NeededForTesting
        public UsageStats(String usageType, long lastTimeUsed, int timesUsed) {
            this.mUsageType = usageType;
            this.mLastTimeUsed = lastTimeUsed;
            this.mTimesUsed = timesUsed;
        }
    }

    @NeededForTesting
    public static class FieldData {
        @NeededForTesting
        final String mDataHashId;
        @NeededForTesting
        final boolean mIsPrimary;
        @NeededForTesting
        final boolean mIsSuperPrimary;
        @NeededForTesting
        final ArrayList<UsageStats> mUsageStatsList;

        @NeededForTesting
        public FieldData(String dataHashId, boolean isPrimary, boolean isSuperPrimary,
                ArrayList<UsageStats> usageStatsList) {
            this.mDataHashId = dataHashId;
            this.mIsPrimary = isPrimary;
            this.mIsSuperPrimary = isSuperPrimary;
            this.mUsageStatsList = usageStatsList;
        }
    }

    @NeededForTesting
    public static class RawContactInfo {
        @NeededForTesting
        final String mBackupId;
        @NeededForTesting
        final String mAccountType;
        @NeededForTesting
        final String mAccountName;
        @NeededForTesting
        final String mDataSet;

        @NeededForTesting
        public RawContactInfo(String backupId, String accountType, String accountName,
                String dataSet) {
            this.mBackupId = backupId;
            this.mAccountType = accountType;
            this.mAccountName = accountName;
            mDataSet = dataSet;
        }
    }

    @NeededForTesting
    public static class AggregationData {
        @NeededForTesting
        final RawContactInfo mRawContactInfo1;
        @NeededForTesting
        final RawContactInfo mRawContactInfo2;
        @NeededForTesting
        final String mType;

        @NeededForTesting
        public AggregationData(RawContactInfo rawContactInfo1, RawContactInfo rawContactInfo2,
                String type) {
            this.mRawContactInfo1 = rawContactInfo1;
            this.mRawContactInfo2 = rawContactInfo2;
            this.mType = type;
        }
    }

    @NeededForTesting
    public static class MetadataEntry {
        @NeededForTesting
        final RawContactInfo mRawContactInfo;
        @NeededForTesting
        final int mSendToVoicemail;
        @NeededForTesting
        final int mStarred;
        @NeededForTesting
        final int mPinned;
        @NeededForTesting
        final ArrayList<FieldData> mFieldDatas;
        @NeededForTesting
        final ArrayList<AggregationData> mAggregationDatas;

        @NeededForTesting
        public MetadataEntry(RawContactInfo rawContactInfo,
                int sendToVoicemail, int starred, int pinned,
                ArrayList<FieldData> fieldDatas,
                ArrayList<AggregationData> aggregationDatas) {
            this.mRawContactInfo = rawContactInfo;
            this.mSendToVoicemail = sendToVoicemail;
            this.mStarred = starred;
            this.mPinned = pinned;
            this.mFieldDatas = fieldDatas;
            this.mAggregationDatas = aggregationDatas;
        }
    }

    @NeededForTesting
    static MetadataEntry parseDataToMetaDataEntry(String inputData) {
        if (TextUtils.isEmpty(inputData)) {
            throw new IllegalArgumentException("Input cannot be empty.");
        }

        try {
            final JSONObject root = new JSONObject(inputData);
            // Parse to get rawContactId and account info.
            final JSONObject uniqueContactJSON = root.getJSONObject(UNIQUE_CONTACT_ID);
            final RawContactInfo rawContactInfo = parseUniqueContact(uniqueContactJSON);

            // Parse contactPrefs to get sendToVoicemail, starred, pinned.
            final JSONObject contactPrefs = root.getJSONObject(CONTACT_PREFS);
            final boolean sendToVoicemail = contactPrefs.has(SEND_TO_VOICEMAIL)
                    ? contactPrefs.getBoolean(SEND_TO_VOICEMAIL) : false;
            final boolean starred = contactPrefs.has(STARRED)
                    ? contactPrefs.getBoolean(STARRED) : false;
            final int pinned = contactPrefs.has(PINNED) ? contactPrefs.getInt(PINNED) : 0;

            // Parse aggregationDatas
            final ArrayList<AggregationData> aggregationsList = new ArrayList<AggregationData>();
            if (root.has(AGGREGATION_DATA)) {
                final JSONArray aggregationDatas = root.getJSONArray(AGGREGATION_DATA);

                for (int i = 0; i < aggregationDatas.length(); i++) {
                    final JSONObject aggregationData = aggregationDatas.getJSONObject(i);
                    final JSONArray contacts = aggregationData.getJSONArray(CONTACT_IDS);

                    if (contacts.length() != 2) {
                        throw new IllegalArgumentException(
                                "There should be two contacts for each aggregation.");
                    }
                    final JSONObject rawContact1 = contacts.getJSONObject(0);
                    final RawContactInfo aggregationContact1 = parseUniqueContact(rawContact1);
                    final JSONObject rawContact2 = contacts.getJSONObject(1);
                    final RawContactInfo aggregationContact2 = parseUniqueContact(rawContact2);
                    final String type = aggregationData.getString(TYPE);
                    if (TextUtils.isEmpty(type)) {
                        throw new IllegalArgumentException("Aggregation type cannot be empty.");
                    }

                    final AggregationData aggregation = new AggregationData(
                            aggregationContact1, aggregationContact2, type);
                    aggregationsList.add(aggregation);
                }
            }

            // Parse fieldDatas
            final ArrayList<FieldData> fieldDatasList = new ArrayList<FieldData>();
            if (root.has(FIELD_DATA)) {
                final JSONArray fieldDatas = root.getJSONArray(FIELD_DATA);

                for (int i = 0; i < fieldDatas.length(); i++) {
                    final JSONObject fieldData = fieldDatas.getJSONObject(i);
                    final String dataHashId = fieldData.getString(FIELD_DATA_ID);
                    if (TextUtils.isEmpty(dataHashId)) {
                        throw new IllegalArgumentException("Field data hash id cannot be empty.");
                    }
                    final JSONObject fieldDataPrefs = fieldData.getJSONObject(FIELD_DATA_PREFS);
                    final boolean isPrimary = fieldDataPrefs.getBoolean(IS_PRIMARY);
                    final boolean isSuperPrimary = fieldDataPrefs.getBoolean(IS_SUPER_PRIMARY);

                    final ArrayList<UsageStats> usageStatsList = new ArrayList<UsageStats>();
                    if (fieldData.has(USAGE_STATS)) {
                        final JSONArray usageStats = fieldData.getJSONArray(USAGE_STATS);
                        for (int j = 0; j < usageStats.length(); j++) {
                            final JSONObject usageStat = usageStats.getJSONObject(j);
                            final String usageType = usageStat.getString(USAGE_TYPE);
                            if (TextUtils.isEmpty(usageType)) {
                                throw new IllegalArgumentException("Usage type cannot be empty.");
                            }
                            final long lastTimeUsed = usageStat.getLong(LAST_TIME_USED);
                            final int usageCount = usageStat.getInt(USAGE_COUNT);

                            final UsageStats usageStatsParsed = new UsageStats(
                                    usageType, lastTimeUsed, usageCount);
                            usageStatsList.add(usageStatsParsed);
                        }
                    }

                    final FieldData fieldDataParse = new FieldData(dataHashId, isPrimary,
                            isSuperPrimary, usageStatsList);
                    fieldDatasList.add(fieldDataParse);
                }
            }
            final MetadataEntry metaDataEntry = new MetadataEntry(rawContactInfo,
                    sendToVoicemail ? 1 : 0, starred ? 1 : 0, pinned,
                    fieldDatasList, aggregationsList);
            return metaDataEntry;
        } catch (JSONException e) {
            throw new IllegalArgumentException("JSON Exception.", e);
        }
    }

    private static RawContactInfo parseUniqueContact(JSONObject uniqueContactJSON) {
        try {
            final String backupId = uniqueContactJSON.getString(CONTACT_ID);
            final String accountName = uniqueContactJSON.getString(ACCOUNT_NAME);
            String accountType = uniqueContactJSON.getString(ACCOUNT_TYPE);
            if (ENUM_VALUE_FOR_GOOGLE_ACCOUNT.equals(accountType)) {
                accountType = GOOGLE_ACCOUNT_TYPE;
            } else if (ENUM_VALUE_FOR_CUSTOM_ACCOUNT.equals(accountType)) {
                accountType = uniqueContactJSON.getString(CUSTOM_ACCOUNT_TYPE);
            } else {
                throw new IllegalArgumentException("Unknown account type.");
            }

            String dataSet = null;
            switch (uniqueContactJSON.getString(DATA_SET)) {
                case ENUM_FOR_PLUS_DATA_SET:
                    dataSet = PLUS_DATA_SET_TYPE;
                    break;
                case ENUM_FOR_CUSTOM_DATA_SET:
                    dataSet = uniqueContactJSON.getString(CUSTOM_DATA_SET);
                    break;
            }
            if (TextUtils.isEmpty(backupId) || TextUtils.isEmpty(accountType)
                    || TextUtils.isEmpty(accountName)) {
                throw new IllegalArgumentException(
                        "Contact backup id, account type, account name cannot be empty.");
            }
            final RawContactInfo rawContactInfo = new RawContactInfo(
                    backupId, accountType, accountName, dataSet);
            return rawContactInfo;
        } catch (JSONException e) {
            throw new IllegalArgumentException("JSON Exception.", e);
        }
    }
}
