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

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.service.carrier.CarrierMessagingService;
import android.service.carrier.ICarrierMessagingService;

import com.android.internal.util.Preconditions;

/**
 * Provides basic structure for platform to connect to the carrier messaging service.
 * <p>
 * <code>
 * CarrierMessagingServiceManager carrierMessagingServiceManager =
 *     new CarrierMessagingServiceManagerImpl();
 * if (carrierMessagingServiceManager.bindToCarrierMessagingService(context, carrierPackageName)) {
 *   // wait for onServiceReady callback
 * } else {
 *   // Unable to bind: handle error.
 * }
 * </code>
 * <p> Upon completion {@link #disposeConnection} should be called to unbind the
 * CarrierMessagingService.
 * @hide
 */
public abstract class CarrierMessagingServiceManager {
    // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
    // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
    private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;

    /**
     * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
     * should be called exactly once.
     *
     * @param context the context
     * @param carrierPackageName the carrier package name
     * @return true upon successfully binding to a carrier messaging service, false otherwise
     */
    public boolean bindToCarrierMessagingService(Context context, String carrierPackageName) {
        Preconditions.checkState(mCarrierMessagingServiceConnection == null);

        Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
        intent.setPackage(carrierPackageName);
        mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
        return context.bindService(intent, mCarrierMessagingServiceConnection,
                Context.BIND_AUTO_CREATE);
    }

    /**
     * Unbinds the carrier messaging service. This method should be called exactly once.
     *
     * @param context the context
     */
    public void disposeConnection(Context context) {
        Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
        context.unbindService(mCarrierMessagingServiceConnection);
        mCarrierMessagingServiceConnection = null;
    }

    /**
     * Implemented by subclasses to use the carrier messaging service once it is ready.
     *
     * @param carrierMessagingService the carrier messaing service interface
     */
    protected abstract void onServiceReady(ICarrierMessagingService carrierMessagingService);

    /**
     * A basic {@link ServiceConnection}.
     */
    private final class CarrierMessagingServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            onServiceReady(ICarrierMessagingService.Stub.asInterface(service));
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }
}
