/*
 * 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.telephony.common;

import android.content.Context;
import android.database.Cursor;
import android.icu.text.Collator;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * Encapsulates data about a phone Contact entry. Typically loaded from the local Contact store.
 */
public class Contact implements Parcelable, Comparable<Contact> {
    private static final String TAG = "CD.Contact";
    private static final String PHONEBOOK_LABEL = "phonebook_label";
    private static final String PHONEBOOK_LABEL_ALT = "phonebook_label_alt";

    /**
     * Contact belongs to TYPE_LETTER if its display name starts with a letter
     */
    private static final int TYPE_LETTER = 1;

    /**
     * Contact belongs to TYPE_DIGIT if its display name starts with a digit
     */
    private static final int TYPE_DIGIT = 2;

    /**
     * Contact belongs to TYPE_OTHER if it does not belong to TYPE_LETTER or TYPE_DIGIT
     * Such as empty display name or the display name starts with "_"
     */
    private static final int TYPE_OTHER = 3;


    /**
     * A reference to the {@link ContactsContract.Contacts#_ID} that this data belongs to. See
     * {@link ContactsContract.Contacts.Entity#CONTACT_ID}
     */
    private long mId;

    /**
     * Whether this contact entry is starred by user.
     */
    private boolean mIsStarred;

    /**
     * Contact-specific information about whether or not a contact has been pinned by the user at
     * a particular position within the system contact application's user interface.
     */
    private int mPinnedPosition;

    /**
     * All phone numbers of this contact mapping to the unique primary key for the raw data entry.
     */
    private List<PhoneNumber> mPhoneNumbers = new ArrayList<>();

    /**
     * The display name.
     * <p>
     * The standard text shown as the contact's display name, based on the best
     * available information for the contact.
     * </p>
     *
     * @see ContactsContract.CommonDataKinds.Phone#DISPLAY_NAME
     */
    private String mDisplayName;

    /**
     * The alternative display name.
     * <p>
     * An alternative representation of the display name, such as "family name first"
     * instead of "given name first" for Western names.  If an alternative is not
     * available, the values should be the same as {@link #mDisplayName}.
     * </p>
     *
     * @see ContactsContract.CommonDataKinds.Phone#DISPLAY_NAME_ALTERNATIVE
     */
    private String mAltDisplayName;

    /**
     * The phonebook label.
     * <p>
     * For {@link #mDisplayName}s starting with letters, label will be the first character of
     * {@link #mDisplayName}. For {@link #mDisplayName}s starting with numbers, the label will
     * be "#". For {@link #mDisplayName}s starting with other characters, the label will be "...".
     * </p>
     */
    private String mPhoneBookLabel;

    /**
     * The alternative phonebook label.
     * <p>
     * It is similar with {@link #mPhoneBookLabel}. But instead of generating from
     * {@link #mDisplayName}, it will use {@link #mAltDisplayName}.
     * </p>
     */
    private String mPhoneBookLabelAlt;

    /**
     * A URI that can be used to retrieve a thumbnail of the contact's photo.
     */
    private Uri mAvatarThumbnailUri;

    /**
     * A URI that can be used to retrieve the contact's full-size photo.
     */
    private Uri mAvatarUri;

    /**
     * An opaque value that contains hints on how to find the contact if its row id changed
     * as a result of a sync or aggregation. If a contact has multiple phone numbers, all phone
     * numbers are recorded in a single entry and they all have the same look up key in a single
     * load.
     */
    private String mLookupKey;

    /**
     * Whether this contact represents a voice mail.
     */
    private boolean mIsVoiceMail;

    private PhoneNumber mPrimaryPhoneNumber;

    /**
     * Parses a Contact entry for a Cursor loaded from the Contact Database.
     */
    public static Contact fromCursor(Context context, Cursor cursor) {
        int contactIdColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
        int starredColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED);
        int pinnedColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PINNED);
        int displayNameColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
        int altDisplayNameColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_ALTERNATIVE);
        int phoneBookLabelColumn = cursor.getColumnIndex(PHONEBOOK_LABEL);
        int phoneBookLabelAltColumn = cursor.getColumnIndex(PHONEBOOK_LABEL_ALT);
        int avatarUriColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.PHOTO_URI);
        int avatarThumbnailColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI);
        int lookupKeyColumn = cursor.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY);

        Contact contact = new Contact();
        contact.mId = cursor.getLong(contactIdColumn);
        contact.mDisplayName = cursor.getString(displayNameColumn);
        contact.mAltDisplayName = cursor.getString(altDisplayNameColumn);
        contact.mPhoneBookLabel = cursor.getString(phoneBookLabelColumn);
        contact.mPhoneBookLabelAlt = cursor.getString(phoneBookLabelAltColumn);

        PhoneNumber number = PhoneNumber.fromCursor(context, cursor);
        contact.mPhoneNumbers.add(number);
        if (number.isPrimary()) {
            contact.mPrimaryPhoneNumber = number;
        }

        contact.mIsStarred = cursor.getInt(starredColumn) > 0;
        contact.mPinnedPosition = cursor.getInt(pinnedColumn);
        contact.mIsVoiceMail = TelecomUtils.isVoicemailNumber(context, number.getNumber());

        String avatarUriStr = cursor.getString(avatarUriColumn);
        contact.mAvatarUri = avatarUriStr == null ? null : Uri.parse(avatarUriStr);

        String avatarThumbnailStringUri = cursor.getString(avatarThumbnailColumn);
        contact.mAvatarThumbnailUri = avatarThumbnailStringUri == null ? null : Uri.parse(
                avatarThumbnailStringUri);

        String lookUpKey = cursor.getString(lookupKeyColumn);
        if (lookUpKey != null) {
            contact.mLookupKey = lookUpKey;
        } else {
            Log.w(TAG, "Look up key is null. Fallback to use display name");
            contact.mLookupKey = contact.mDisplayName;
        }
        return contact;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Contact && mLookupKey.equals(((Contact) obj).mLookupKey);
    }

    @Override
    public int hashCode() {
        return mLookupKey.hashCode();
    }

    @Override
    public String toString() {
        return mDisplayName + mPhoneNumbers;
    }

    public String getDisplayName() {
        return mDisplayName;
    }

    /**
     * Returns alternative display name.
     */
    public String getAltDisplayName() {
        return mAltDisplayName;
    }

    /**
     * Returns {@link #mPhoneBookLabel}
     */
    public String getPhonebookLabel() {
        return mPhoneBookLabel;
    }

    /**
     * Returns {@link #mPhoneBookLabelAlt}
     */
    public String getPhonebookLabelAlt() {
        return mPhoneBookLabelAlt;
    }

    public boolean isVoicemail() {
        return mIsVoiceMail;
    }

    @Nullable
    public Uri getAvatarUri() {
        return mAvatarThumbnailUri != null ? mAvatarThumbnailUri : mAvatarUri;
    }

    public String getLookupKey() {
        return mLookupKey;
    }

    public Uri getLookupUri() {
        return ContactsContract.Contacts.getLookupUri(mId, mLookupKey);
    }

    /** Return all phone numbers associated with this contact. */
    public List<PhoneNumber> getNumbers() {
        return mPhoneNumbers;
    }

    /** Return the aggregated contact id. */
    public long getId() {
        return mId;
    }

    public boolean isStarred() {
        return mIsStarred;
    }

    public int getPinnedPosition() {
        return mPinnedPosition;
    }

    /**
     * Merges a Contact entry with another if they represent different numbers of the same contact.
     *
     * @return A merged contact.
     */
    public Contact merge(Contact contact) {
        if (equals(contact)) {
            for (PhoneNumber phoneNumber : contact.mPhoneNumbers) {
                int indexOfPhoneNumber = mPhoneNumbers.indexOf(phoneNumber);
                if (indexOfPhoneNumber < 0) {
                    mPhoneNumbers.add(phoneNumber);
                } else {
                    PhoneNumber existingPhoneNumber = mPhoneNumbers.get(indexOfPhoneNumber);
                    existingPhoneNumber.merge(phoneNumber);
                }
            }
            if (contact.mPrimaryPhoneNumber != null) {
                mPrimaryPhoneNumber = contact.mPrimaryPhoneNumber.merge(mPrimaryPhoneNumber);
            }
        }
        return this;
    }

    /**
     * Looks up a {@link PhoneNumber} of this contact for the given phone number. Returns {@code
     * null} if this contact doesn't contain the given phone number.
     */
    @Nullable
    public PhoneNumber getPhoneNumber(Context context, String number) {
        I18nPhoneNumberWrapper i18nPhoneNumber = I18nPhoneNumberWrapper.Factory.INSTANCE.get(
                context, number);
        for (PhoneNumber phoneNumber : mPhoneNumbers) {
            if (phoneNumber.getI18nPhoneNumberWrapper().equals(i18nPhoneNumber)) {
                return phoneNumber;
            }
        }
        return null;
    }

    public PhoneNumber getPrimaryPhoneNumber() {
        return mPrimaryPhoneNumber;
    }

    /** Return if this contact has a primary phone number. */
    public boolean hasPrimaryPhoneNumber() {
        return mPrimaryPhoneNumber != null;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mId);
        dest.writeBoolean(mIsStarred);
        dest.writeInt(mPinnedPosition);
        dest.writeInt(mPhoneNumbers.size());
        for (PhoneNumber phoneNumber : mPhoneNumbers) {
            dest.writeParcelable(phoneNumber, flags);
        }
        dest.writeString(mDisplayName);
        dest.writeString(mAltDisplayName);
        dest.writeString(mPhoneBookLabel);
        dest.writeString(mPhoneBookLabelAlt);
        dest.writeParcelable(mAvatarThumbnailUri, 0);
        dest.writeParcelable(mAvatarUri, 0);
        dest.writeString(mLookupKey);
        dest.writeBoolean(mIsVoiceMail);
    }

    public static final Creator<Contact> CREATOR = new Creator<Contact>() {
        @Override
        public Contact createFromParcel(Parcel source) {
            return Contact.fromParcel(source);
        }

        @Override
        public Contact[] newArray(int size) {
            return new Contact[size];
        }
    };

    /** Create {@link Contact} object from saved parcelable. */
    private static Contact fromParcel(Parcel source) {
        Contact contact = new Contact();
        contact.mId = source.readLong();
        contact.mIsStarred = source.readBoolean();
        contact.mPinnedPosition = source.readInt();
        int phoneNumberListLength = source.readInt();
        contact.mPhoneNumbers = new ArrayList<>();
        for (int i = 0; i < phoneNumberListLength; i++) {
            PhoneNumber phoneNumber = source.readParcelable(PhoneNumber.class.getClassLoader());
            contact.mPhoneNumbers.add(phoneNumber);
            if (phoneNumber.isPrimary()) {
                contact.mPrimaryPhoneNumber = phoneNumber;
            }
        }
        contact.mDisplayName = source.readString();
        contact.mAltDisplayName = source.readString();
        contact.mPhoneBookLabel = source.readString();
        contact.mPhoneBookLabelAlt = source.readString();
        contact.mAvatarThumbnailUri = source.readParcelable(Uri.class.getClassLoader());
        contact.mAvatarUri = source.readParcelable(Uri.class.getClassLoader());
        contact.mLookupKey = source.readString();
        contact.mIsVoiceMail = source.readBoolean();
        return contact;
    }

    @Override
    public int compareTo(Contact otherContact) {
        // Use a helper function to classify Contacts
        // and by default, it should be compared by first name order.
        return compareByDisplayName(otherContact);
    }

    /**
     * Compares contacts by their {@link #mDisplayName} in an order of
     * letters, numbers, then special characters.
     */
    public int compareByDisplayName(@NonNull Contact otherContact) {
        return compareNames(mDisplayName, otherContact.getDisplayName(),
                mPhoneBookLabel, otherContact.getPhonebookLabel());
    }

    /**
     * Compares contacts by their {@link #mAltDisplayName} in an order of
     * letters, numbers, then special characters.
     */
    public int compareByAltDisplayName(@NonNull Contact otherContact) {
        return compareNames(mAltDisplayName, otherContact.getAltDisplayName(),
                mPhoneBookLabelAlt, otherContact.getPhonebookLabelAlt());
    }

    /**
     * Compares two strings in an order of letters, numbers, then special characters.
     */
    private int compareNames(String name, String otherName, String label, String otherLabel) {
        int type = getNameType(label);
        int otherType = getNameType(otherLabel);
        if (type != otherType) {
            return Integer.compare(type, otherType);
        }
        Collator collator = Collator.getInstance();
        return collator.compare(name == null ? "" : name, otherName == null ? "" : otherName);
    }

    /**
     * Returns the type of the name string.
     * Types can be {@link #TYPE_LETTER}, {@link #TYPE_DIGIT} and {@link #TYPE_OTHER}.
     */
    private static int getNameType(String label) {
        // A helper function to classify Contacts
        if (!TextUtils.isEmpty(label)) {
            if (Character.isLetter(label.charAt(0))) {
                return TYPE_LETTER;
            }
            if (label.contains("#")) {
                return TYPE_DIGIT;
            }
        }
        return TYPE_OTHER;
    }
}
