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

import android.os.Build;
import android.support.annotation.RequiresApi;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

/**
 * Holds data for a SIM card in the device.
 */
public class SimCard {

    private static final String TAG = "SimCard";

    public static final int NO_SUBSCRIPTION_ID = -1;

    // This state is created from the info we get from the system
    private final String mSimId;
    private final int mSubscriptionId;
    private final CharSequence mCarrierName;
    private final CharSequence mDisplayName;
    private final String mPhoneNumber;
    private final String mCountryCode;

    // This is our own state that we associate with SIM cards. Currently these are only used
    // in the GoogleContacts app.
    // Note: these are logically immutable but are not final to reduce required constructor
    // parameters
    private boolean mDismissed = false;
    private boolean mImported = false;

    private List<SimContact> mContacts;

    public SimCard(SimCard other) {
        mSimId = other.mSimId;
        mSubscriptionId = other.mSubscriptionId;
        mCarrierName = other.mCarrierName;
        mDisplayName = other.mDisplayName;
        mPhoneNumber = other.mPhoneNumber;
        mCountryCode = other.mCountryCode;
        mDismissed = other.mDismissed;
        mImported = other.mImported;
        if (other.mContacts != null) {
            mContacts = new ArrayList<>(other.mContacts);
        }
    }

    public SimCard(String simId, int subscriptionId, CharSequence carrierName,
            CharSequence displayName, String phoneNumber, String countryCode) {
        mSimId = simId;
        mSubscriptionId = subscriptionId;
        mCarrierName = carrierName;
        mDisplayName = displayName;
        mPhoneNumber = phoneNumber;
        mCountryCode = countryCode != null ? countryCode.toUpperCase(Locale.US) : null;
    }

    public SimCard(String simId, CharSequence carrierName,
            CharSequence displayName, String phoneNumber, String countryCode) {
        this(simId, NO_SUBSCRIPTION_ID, carrierName, displayName, phoneNumber, countryCode);
    }

    public String getSimId() {
        return mSimId;
    }

    public int getSubscriptionId() {
        return mSubscriptionId;
    }

    public boolean hasValidSubscriptionId() {
        return mSubscriptionId != NO_SUBSCRIPTION_ID;
    }

    public CharSequence getDisplayName() {
        return mDisplayName;
    }

    public String getPhone() {
        return mPhoneNumber;
    }

    public CharSequence getFormattedPhone() {
        if (mPhoneNumber == null) {
            return null;
        }
        return PhoneNumberUtils.formatNumber(mPhoneNumber, mCountryCode);
    }

    public boolean hasPhone() {
        return mPhoneNumber != null;
    }

    public String getCountryCode() {
        return mCountryCode;
    }

    /**
     * Returns whether the contacts for this SIM card have been initialized.
     */
    public boolean areContactsAvailable() {
        return mContacts != null;
    }

    /**
     * Returns whether this SIM card has any SIM contacts.
     *
     * A precondition of this method is that the contacts have been initialized.
     */
    public boolean hasContacts() {
        if (mContacts == null) {
            throw new IllegalStateException("Contacts not loaded.");
        }
        return !mContacts.isEmpty();
    }

    /**
     * Returns the number of contacts stored on this SIM card.
     *
     * A precondition of this method is that the contacts have been initialized.
     */
    public int getContactCount() {
        if (mContacts == null) {
            throw new IllegalStateException("Contacts not loaded.");
        }
        return mContacts.size();
    }

    public boolean isDismissed() {
        return mDismissed;
    }

    public boolean isImported() {
        return mImported;
    }

    public boolean isImportable() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "isImportable: isDismissed? " + isDismissed() +
                    " isImported? " + isImported() + " contacts=" + mContacts);
        }
        return !isDismissed() && !isImported() && hasContacts();
    }

    /**
     * Returns the contacts for this SIM card or null if the contacts have not been initialized.
     */
    public List<SimContact> getContacts() {
        return mContacts;
    }

    public SimCard withImportAndDismissStates(boolean imported, boolean dismissed) {
        SimCard copy = new SimCard(this);
        copy.mImported = imported;
        copy.mDismissed = dismissed;
        return copy;
    }

    public SimCard withImportedState(boolean imported) {
        return withImportAndDismissStates(imported, mDismissed);
    }

    public SimCard withDismissedState(boolean dismissed) {
        return withImportAndDismissStates(mImported, dismissed);
    }

    public SimCard withContacts(List<SimContact> contacts) {
        final SimCard copy = new SimCard(this);
        copy.mContacts = contacts;
        return copy;
    }

    public SimCard withContacts(SimContact... contacts) {
        final SimCard copy = new SimCard(this);
        copy.mContacts = Arrays.asList(contacts);
        return copy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        SimCard simCard = (SimCard) o;

        return mSubscriptionId == simCard.mSubscriptionId && mDismissed == simCard.mDismissed &&
                mImported == simCard.mImported && Objects.equals(mSimId, simCard.mSimId) &&
                Objects.equals(mPhoneNumber, simCard.mPhoneNumber) &&
                Objects.equals(mCountryCode, simCard.mCountryCode);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(mSimId, mPhoneNumber, mCountryCode);
        result = 31 * result + mSubscriptionId;
        result = 31 * result + (mDismissed ? 1 : 0);
        result = 31 * result + (mImported ? 1 : 0);
        return result;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
    public static SimCard create(SubscriptionInfo info) {
        return new SimCard(info.getIccId(), info.getSubscriptionId(),
                info.getCarrierName(), info.getDisplayName(), info.getNumber(),
                info.getCountryIso());
    }

    public static SimCard create(TelephonyManager telephony, String displayLabel) {
        if (telephony.getSimState() == TelephonyManager.SIM_STATE_READY) {
            return new SimCard(telephony.getSimSerialNumber(),
                    telephony.getSimOperatorName(), displayLabel, telephony.getLine1Number(),
                    telephony.getSimCountryIso());
        } else {
            // This should never happen but in case it does just fallback to an "empty" instance
            return new SimCard(/* SIM id */ "", /* operator name */ null, displayLabel,
                    /* phone number */ "", /* Country code */ null);
        }
    }
}
