/*
 * 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.
 */

package com.android.services.telephony.sip;

import android.content.Context;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Manages the {@link PhoneAccount} entries for SIP calling.
 */
public final class SipAccountRegistry {
    private final class AccountEntry {
        private final SipProfile mProfile;

        AccountEntry(SipProfile profile) {
            mProfile = profile;
        }

        SipProfile getProfile() {
            return mProfile;
        }

        /**
         * Starts the SIP service associated with the SIP profile.
         *
         * @param sipManager The SIP manager.
         * @param context The context.
         * @param isReceivingCalls {@code True} if the sip service is being started to make and
         *          receive calls.  {@code False} if the sip service is being started only for
         *          outgoing calls.
         * @return {@code True} if the service started successfully.
         */
        boolean startSipService(SipManager sipManager, Context context, boolean isReceivingCalls) {
            if (VERBOSE) log("startSipService, profile: " + mProfile);
            try {
                // Stop the Sip service for the profile if it is already running.  This is important
                // if we are changing the state of the "receive calls" option.
                sipManager.close(mProfile.getUriString());

                // Start the sip service for the profile.
                if (isReceivingCalls) {
                    sipManager.open(
                            mProfile,
                            SipUtil.createIncomingCallPendingIntent(context,
                                    mProfile.getUriString()),
                            null);
                } else {
                    sipManager.open(mProfile);
                }
                return true;
            } catch (SipException e) {
                log("startSipService, profile: " + mProfile.getProfileName() +
                        ", exception: " + e);
            }
            return false;
        }

        /**
         * Stops the SIP service associated with the SIP profile.  The {@code SipAccountRegistry} is
         * informed when the service has been stopped via an intent which triggers
         * {@link SipAccountRegistry#removeSipProfile(String)}.
         *
         * @param sipManager The SIP manager.
         * @return {@code True} if stop was successful.
         */
        boolean stopSipService(SipManager sipManager) {
            try {
                sipManager.close(mProfile.getUriString());
                return true;
            } catch (Exception e) {
                log("stopSipService, stop failed for profile: " + mProfile.getUriString() +
                        ", exception: " + e);
            }
            return false;
        }
    }

    private static final String PREFIX = "[SipAccountRegistry] ";
    private static final boolean VERBOSE = false; /* STOP SHIP if true */
    private static final SipAccountRegistry INSTANCE = new SipAccountRegistry();

    private final List<AccountEntry> mAccounts = new CopyOnWriteArrayList<>();

    private SipAccountRegistry() {}

    public static SipAccountRegistry getInstance() {
        return INSTANCE;
    }

    void setup(Context context) {
        verifyAndPurgeInvalidPhoneAccounts(context);
        startSipProfilesAsync(context, (String) null, false);
    }

    /**
     * Checks the existing SIP phone {@link PhoneAccount}s registered with telecom and deletes any
     * invalid accounts.
     *
     * @param context The context.
     */
    void verifyAndPurgeInvalidPhoneAccounts(Context context) {
        TelecomManager telecomManager = TelecomManager.from(context);
        SipProfileDb profileDb = new SipProfileDb(context);
        List<PhoneAccountHandle> accountHandles = telecomManager.getPhoneAccountsSupportingScheme(
                PhoneAccount.SCHEME_SIP);

        for (PhoneAccountHandle accountHandle : accountHandles) {
            String profileName = SipUtil.getSipProfileNameFromPhoneAccount(accountHandle);
            SipProfile profile = profileDb.retrieveSipProfileFromName(profileName);
            if (profile == null) {
                log("verifyAndPurgeInvalidPhoneAccounts, deleting account: " + accountHandle);
                telecomManager.unregisterPhoneAccount(accountHandle);
            }
        }
    }

    /**
     * Starts the SIP service for the specified SIP profile and ensures it has a valid registered
     * {@link PhoneAccount}.
     *
     * @param context The context.
     * @param sipProfileName The name of the {@link SipProfile} to start, or {@code null} for all.
     * @param enableProfile Sip account should be enabled
     */
    void startSipService(Context context, String sipProfileName, boolean enableProfile) {
        startSipProfilesAsync(context, sipProfileName, enableProfile);
    }

    /**
     * Removes a {@link SipProfile} from the account registry.  Does not stop/close the associated
     * SIP service (this method is invoked via an intent from the SipService once a profile has
     * been stopped/closed).
     *
     * @param sipProfileName Name of the SIP profile.
     */
    void removeSipProfile(String sipProfileName) {
        AccountEntry accountEntry = getAccountEntry(sipProfileName);

        if (accountEntry != null) {
            mAccounts.remove(accountEntry);
        }
    }

    /**
     * Stops a SIP profile and un-registers its associated {@link android.telecom.PhoneAccount}.
     * Called after a SIP profile is deleted.  The {@link AccountEntry} will be removed when the
     * service has been stopped.  The {@code SipService} fires the {@code ACTION_SIP_REMOVE_PHONE}
     * intent, which triggers {@link SipAccountRegistry#removeSipProfile(String)} to perform the
     * removal.
     *
     * @param context The context.
     * @param sipProfileName Name of the SIP profile.
     */
    void stopSipService(Context context, String sipProfileName) {
        // Stop the sip service for the profile.
        AccountEntry accountEntry = getAccountEntry(sipProfileName);
        if (accountEntry != null ) {
            SipManager sipManager = SipManager.newInstance(context);
            accountEntry.stopSipService(sipManager);
        }

        // Un-register its PhoneAccount.
        PhoneAccountHandle handle = SipUtil.createAccountHandle(context, sipProfileName);
        TelecomManager.from(context).unregisterPhoneAccount(handle);
    }

    /**
     * Causes the SIP service to be restarted for all {@link SipProfile}s.  For example, if the user
     * toggles the "receive calls" option for SIP, this method handles restarting the SIP services
     * in the new mode.
     *
     * @param context The context.
     */
    public void restartSipService(Context context) {
        startSipProfiles(context, null, false);
    }

    /**
     * Performs an asynchronous call to
     * {@link SipAccountRegistry#startSipProfiles(android.content.Context, String)}, starting the
     * specified SIP profile and registering its {@link android.telecom.PhoneAccount}.
     *
     * @param context The context.
     * @param sipProfileName Name of the SIP profile.
     * @param enableProfile Sip account should be enabled.
     */
    private void startSipProfilesAsync(
            final Context context, final String sipProfileName, final boolean enableProfile) {
        if (VERBOSE) log("startSipProfiles, start auto registration");

        new Thread(new Runnable() {
            @Override
            public void run() {
                startSipProfiles(context, sipProfileName, enableProfile);
            }}
        ).start();
    }

    /**
     * Loops through all SIP accounts from the SIP database, starts each service and registers
     * each with the telecom framework. If a specific sipProfileName is specified, this will only
     * register the associated SIP account.
     *
     * @param context The context.
     * @param sipProfileName A specific SIP profile Name to start, or {@code null} to start all.
     * @param enableProfile Sip account should be enabled.
     */
    private void startSipProfiles(Context context, String sipProfileName, boolean enableProfile) {
        final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
        boolean isReceivingCalls = sipSharedPreferences.isReceivingCallsEnabled();
        String primaryProfile = sipSharedPreferences.getPrimaryAccount();
        TelecomManager telecomManager = TelecomManager.from(context);
        SipManager sipManager = SipManager.newInstance(context);
        SipProfileDb profileDb = new SipProfileDb(context);
        List<SipProfile> sipProfileList = profileDb.retrieveSipProfileList();

        for (SipProfile profile : sipProfileList) {
            // Register a PhoneAccount for the profile and optionally enable the primary
            // profile.
            if (sipProfileName == null || sipProfileName.equals(profile.getProfileName())) {
                PhoneAccount phoneAccount = SipUtil.createPhoneAccount(context, profile);
                telecomManager.registerPhoneAccount(phoneAccount);
                if (enableProfile) {
                    telecomManager.enablePhoneAccount(phoneAccount.getAccountHandle(), true);
                }
                startSipServiceForProfile(profile, sipManager, context, isReceivingCalls);
            }
        }

        if (primaryProfile != null) {
            // Remove the primary account shared preference, ensuring the migration does not
            // occur again in the future.
            sipSharedPreferences.cleanupPrimaryAccountSetting();
        }
    }

    /**
     * Starts the SIP service for a sip profile and saves a new {@code AccountEntry} in the
     * registry.
     *
     * @param profile The {@link SipProfile} to start.
     * @param sipManager The SIP manager.
     * @param context The context.
     * @param isReceivingCalls {@code True} if the profile should be started such that it can
     *      receive incoming calls.
     */
    private void startSipServiceForProfile(SipProfile profile, SipManager sipManager,
            Context context, boolean isReceivingCalls) {
        removeSipProfile(profile.getUriString());

        AccountEntry entry = new AccountEntry(profile);
        if (entry.startSipService(sipManager, context, isReceivingCalls)) {
            mAccounts.add(entry);
        }
    }

    /**
     * Retrieves the {@link AccountEntry} from the registry with the specified name.
     *
     * @param sipProfileName Name of the SIP profile to retrieve.
     * @return The {@link AccountEntry}, or {@code null} is it was not found.
     */
    private AccountEntry getAccountEntry(String sipProfileName) {
        for (AccountEntry entry : mAccounts) {
            if (Objects.equals(sipProfileName, entry.getProfile().getProfileName())) {
                return entry;
            }
        }
        return null;
    }

    private void log(String message) {
        Log.d(SipUtil.LOG_TAG, PREFIX + message);
    }
}
