/*
 * Copyright 2017 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.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.NetworkRegistrationInfo.Domain;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;

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

/**
 * Base class of network service. Services that extend NetworkService must register the service in
 * their AndroidManifest to be detected by the framework. They must be protected by the permission
 * "android.permission.BIND_TELEPHONY_NETWORK_SERVICE". The network service definition in the
 * manifest must follow the following format:
 * ...
 * <service android:name=".xxxNetworkService"
 *     android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" >
 *     <intent-filter>
 *         <action android:name="android.telephony.NetworkService" />
 *     </intent-filter>
 * </service>
 * @hide
 */
@SystemApi
public abstract class NetworkService extends Service {

    private final String TAG = NetworkService.class.getSimpleName();

    public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";

    private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER                 = 1;
    private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER                 = 2;
    private static final int NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS            = 3;
    private static final int NETWORK_SERVICE_GET_REGISTRATION_INFO                           = 4;
    private static final int NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE                        = 5;
    private static final int NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE                      = 6;
    private static final int NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED                 = 7;


    private final HandlerThread mHandlerThread;

    private final NetworkServiceHandler mHandler;

    private final SparseArray<NetworkServiceProvider> mServiceMap = new SparseArray<>();

    /**
     * @hide
     */
    @VisibleForTesting
    public final INetworkServiceWrapper mBinder = new INetworkServiceWrapper();

    /**
     * The abstract class of the actual network service implementation. The network service provider
     * must extend this class to support network connection. Note that each instance of network
     * service is associated with one physical SIM slot.
     */
    public abstract class NetworkServiceProvider implements AutoCloseable {
        private final int mSlotIndex;

        private final List<INetworkServiceCallback>
                mNetworkRegistrationInfoChangedCallbacks = new ArrayList<>();

        /**
         * Constructor
         * @param slotIndex SIM slot id the data service provider associated with.
         */
        public NetworkServiceProvider(int slotIndex) {
            mSlotIndex = slotIndex;
        }

        /**
         * @return SIM slot index the network service associated with.
         */
        public final int getSlotIndex() {
            return mSlotIndex;
        }

        /**
         * API to get network registration info. The result will be passed to the callback.
         * @param domain Network domain
         * @param callback The callback for reporting network registration info
         */
        public void getNetworkRegistrationInfo(@Domain int domain,
                                               @NonNull NetworkServiceCallback callback) {
            callback.onGetNetworkRegistrationInfoComplete(
                    NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
        }

        /**
         * Notify the system that network registration info is changed.
         */
        public final void notifyNetworkRegistrationInfoChanged() {
            mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED,
                    mSlotIndex, 0, null).sendToTarget();
        }

        private void registerForInfoChanged(@NonNull INetworkServiceCallback callback) {
            synchronized (mNetworkRegistrationInfoChangedCallbacks) {
                mNetworkRegistrationInfoChangedCallbacks.add(callback);
            }
        }

        private void unregisterForInfoChanged(@NonNull INetworkServiceCallback callback) {
            synchronized (mNetworkRegistrationInfoChangedCallbacks) {
                mNetworkRegistrationInfoChangedCallbacks.remove(callback);
            }
        }

        private void notifyInfoChangedToCallbacks() {
            for (INetworkServiceCallback callback : mNetworkRegistrationInfoChangedCallbacks) {
                try {
                    callback.onNetworkStateChanged();
                } catch (RemoteException exception) {
                    // Doing nothing.
                }
            }
        }

        /**
         * Called when the instance of network service is destroyed (e.g. got unbind or binder died)
         * or when the network service provider is removed. The extended class should implement this
         * method to perform cleanup works.
         */
        @Override
        public abstract void close();
    }

    private class NetworkServiceHandler extends Handler {

        NetworkServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message message) {
            final int slotIndex = message.arg1;
            final INetworkServiceCallback callback = (INetworkServiceCallback) message.obj;

            NetworkServiceProvider serviceProvider = mServiceMap.get(slotIndex);

            switch (message.what) {
                case NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER:
                    // If the service provider doesn't exist yet, we try to create it.
                    if (serviceProvider == null) {
                        mServiceMap.put(slotIndex, onCreateNetworkServiceProvider(slotIndex));
                    }
                    break;
                case NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER:
                    // If the service provider doesn't exist yet, we try to create it.
                    if (serviceProvider != null) {
                        serviceProvider.close();
                        mServiceMap.remove(slotIndex);
                    }
                    break;
                case NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS:
                    for (int i = 0; i < mServiceMap.size(); i++) {
                        serviceProvider = mServiceMap.get(i);
                        if (serviceProvider != null) {
                            serviceProvider.close();
                        }
                    }
                    mServiceMap.clear();
                    break;
                case NETWORK_SERVICE_GET_REGISTRATION_INFO:
                    if (serviceProvider == null) break;
                    int domainId = message.arg2;
                    serviceProvider.getNetworkRegistrationInfo(domainId,
                            new NetworkServiceCallback(callback));

                    break;
                case NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE:
                    if (serviceProvider == null) break;
                    serviceProvider.registerForInfoChanged(callback);
                    break;
                case NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE:
                    if (serviceProvider == null) break;
                    serviceProvider.unregisterForInfoChanged(callback);
                    break;
                case NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED:
                    if (serviceProvider == null) break;
                    serviceProvider.notifyInfoChangedToCallbacks();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * Default constructor.
     */
    public NetworkService() {
        mHandlerThread = new HandlerThread(TAG);
        mHandlerThread.start();

        mHandler = new NetworkServiceHandler(mHandlerThread.getLooper());
        log("network service created");
    }

    /**
     * Create the instance of {@link NetworkServiceProvider}. Network service provider must override
     * this method to facilitate the creation of {@link NetworkServiceProvider} instances. The system
     * will call this method after binding the network service for each active SIM slot id.
     *
     * @param slotIndex SIM slot id the network service associated with.
     * @return Network service object
     */
    @Nullable
    public abstract NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex);

    @Override
    public IBinder onBind(Intent intent) {
        if (intent == null || !NETWORK_SERVICE_INTERFACE.equals(intent.getAction())) {
            loge("Unexpected intent " + intent);
            return null;
        }

        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS, 0,
                0, null).sendToTarget();

        return false;
    }

    /** @hide */
    @Override
    public void onDestroy() {
        mHandlerThread.quit();
        super.onDestroy();
    }

    /**
     * A wrapper around INetworkService that forwards calls to implementations of
     * {@link NetworkService}.
     */
    private class INetworkServiceWrapper extends INetworkService.Stub {

        @Override
        public void createNetworkServiceProvider(int slotIndex) {
            mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotIndex,
                    0, null).sendToTarget();
        }

        @Override
        public void removeNetworkServiceProvider(int slotIndex) {
            mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotIndex,
                    0, null).sendToTarget();
        }

        @Override
        public void getNetworkRegistrationInfo(
                int slotIndex, int domain, INetworkServiceCallback callback) {
            mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_INFO, slotIndex,
                    domain, callback).sendToTarget();
        }

        @Override
        public void registerForNetworkRegistrationInfoChanged(
                int slotIndex, INetworkServiceCallback callback) {
            mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE, slotIndex,
                    0, callback).sendToTarget();
        }

        @Override
        public void unregisterForNetworkRegistrationInfoChanged(
                int slotIndex, INetworkServiceCallback callback) {
            mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE, slotIndex,
                    0, callback).sendToTarget();
        }
    }

    private final void log(String s) {
        Rlog.d(TAG, s);
    }

    private final void loge(String s) {
        Rlog.e(TAG, s);
    }
}
