/*
 * Copyright (C) 2013 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.internal.telephony.dataconnection;

import android.content.Context;
import android.net.INetworkPolicyListener;
import android.net.LinkAddress;
import android.net.LinkProperties.CompareResult;
import android.net.NetworkPolicyManager;
import android.net.NetworkUtils;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.PhoneStateListener;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.telephony.data.DataCallResponse;

import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Data Connection Controller which is a package visible class and controls
 * multiple data connections. For instance listening for unsolicited messages
 * and then demultiplexing them to the appropriate DC.
 */
public class DcController extends StateMachine {
    private static final boolean DBG = true;
    private static final boolean VDBG = false;

    private final Phone mPhone;
    private final DcTracker mDct;
    private final DataServiceManager mDataServiceManager;
    private final DcTesterDeactivateAll mDcTesterDeactivateAll;

    // package as its used by Testing code
    // @GuardedBy("mDcListAll")
    final ArrayList<DataConnection> mDcListAll = new ArrayList<>();
    // @GuardedBy("mDcListAll")
    private final HashMap<Integer, DataConnection> mDcListActiveByCid = new HashMap<>();

    /**
     * Constants for the data connection activity:
     * physical link down/up
     *
     * TODO: Move to RILConstants.java
     */
    static final int DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE = 0;
    static final int DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT = 1;
    static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
    static final int DATA_CONNECTION_ACTIVE_UNKNOWN = Integer.MAX_VALUE;

    private DccDefaultState mDccDefaultState = new DccDefaultState();

    final TelephonyManager mTelephonyManager;
    final NetworkPolicyManager mNetworkPolicyManager;

    private PhoneStateListener mPhoneStateListener;

    //mExecutingCarrierChange tracks whether the phone is currently executing
    //carrier network change
    private volatile boolean mExecutingCarrierChange;

    /**
     * Constructor.
     *
     * @param name to be used for the Controller
     * @param phone the phone associated with Dcc and Dct
     * @param dct the DataConnectionTracker associated with Dcc
     * @param dataServiceManager the data service manager that manages data services
     * @param handler defines the thread/looper to be used with Dcc
     */
    private DcController(String name, Phone phone, DcTracker dct,
                         DataServiceManager dataServiceManager, Handler handler) {
        super(name, handler);
        setLogRecSize(300);
        log("E ctor");
        mPhone = phone;
        mDct = dct;
        mDataServiceManager = dataServiceManager;
        addState(mDccDefaultState);
        setInitialState(mDccDefaultState);
        log("X ctor");

        mPhoneStateListener = new PhoneStateListener(handler.getLooper()) {
            @Override
            public void onCarrierNetworkChange(boolean active) {
                mExecutingCarrierChange = active;
            }
        };

        mTelephonyManager = (TelephonyManager) phone.getContext()
                .getSystemService(Context.TELEPHONY_SERVICE);
        mNetworkPolicyManager = (NetworkPolicyManager) phone.getContext()
                .getSystemService(Context.NETWORK_POLICY_SERVICE);

        mDcTesterDeactivateAll = (Build.IS_DEBUGGABLE)
                ? new DcTesterDeactivateAll(mPhone, DcController.this, getHandler())
                : null;

        if (mTelephonyManager != null) {
            mTelephonyManager.listen(mPhoneStateListener,
                    PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
        }
    }

    public static DcController makeDcc(Phone phone, DcTracker dct,
                                       DataServiceManager dataServiceManager, Handler handler) {
        DcController dcc = new DcController("Dcc", phone, dct, dataServiceManager, handler);
        return dcc;
    }

    void dispose() {
        log("dispose: call quiteNow()");
        if(mTelephonyManager != null) mTelephonyManager.listen(mPhoneStateListener, 0);
        quitNow();
    }

    void addDc(DataConnection dc) {
        synchronized (mDcListAll) {
            mDcListAll.add(dc);
        }
    }

    void removeDc(DataConnection dc) {
        synchronized (mDcListAll) {
            mDcListActiveByCid.remove(dc.mCid);
            mDcListAll.remove(dc);
        }
    }

    public void addActiveDcByCid(DataConnection dc) {
        if (DBG && dc.mCid < 0) {
            log("addActiveDcByCid dc.mCid < 0 dc=" + dc);
        }
        synchronized (mDcListAll) {
            mDcListActiveByCid.put(dc.mCid, dc);
        }
    }

    public DataConnection getActiveDcByCid(int cid) {
        synchronized (mDcListAll) {
            return mDcListActiveByCid.get(cid);
        }
    }

    void removeActiveDcByCid(DataConnection dc) {
        synchronized (mDcListAll) {
            DataConnection removedDc = mDcListActiveByCid.remove(dc.mCid);
            if (DBG && removedDc == null) {
                log("removeActiveDcByCid removedDc=null dc=" + dc);
            }
        }
    }

    boolean isExecutingCarrierChange() {
        return mExecutingCarrierChange;
    }

    private final INetworkPolicyListener mListener = new NetworkPolicyManager.Listener() {
        @Override
        public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
            if (mPhone == null || mPhone.getSubId() != subId) return;

            final HashMap<Integer, DataConnection> dcListActiveByCid;
            synchronized (mDcListAll) {
                dcListActiveByCid = new HashMap<>(mDcListActiveByCid);
            }
            for (DataConnection dc : dcListActiveByCid.values()) {
                dc.onSubscriptionOverride(overrideMask, overrideValue);
            }
        }
    };

    private class DccDefaultState extends State {
        @Override
        public void enter() {
            if (mPhone != null && mDataServiceManager.getTransportType()
                    == TransportType.WWAN) {
                mPhone.mCi.registerForRilConnected(getHandler(),
                        DataConnection.EVENT_RIL_CONNECTED, null);
            }

            mDataServiceManager.registerForDataCallListChanged(getHandler(),
                    DataConnection.EVENT_DATA_STATE_CHANGED);

            if (mNetworkPolicyManager != null) {
                mNetworkPolicyManager.registerListener(mListener);
            }
        }

        @Override
        public void exit() {
            if (mPhone != null & mDataServiceManager.getTransportType()
                    == TransportType.WWAN) {
                mPhone.mCi.unregisterForRilConnected(getHandler());
            }
            mDataServiceManager.unregisterForDataCallListChanged(getHandler());

            if (mDcTesterDeactivateAll != null) {
                mDcTesterDeactivateAll.dispose();
            }
            if (mNetworkPolicyManager != null) {
                mNetworkPolicyManager.unregisterListener(mListener);
            }
        }

        @Override
        public boolean processMessage(Message msg) {
            AsyncResult ar;

            switch (msg.what) {
                case DataConnection.EVENT_RIL_CONNECTED:
                    ar = (AsyncResult)msg.obj;
                    if (ar.exception == null) {
                        if (DBG) {
                            log("DccDefaultState: msg.what=EVENT_RIL_CONNECTED mRilVersion=" +
                                ar.result);
                        }
                    } else {
                        log("DccDefaultState: Unexpected exception on EVENT_RIL_CONNECTED");
                    }
                    break;

                case DataConnection.EVENT_DATA_STATE_CHANGED:
                    ar = (AsyncResult)msg.obj;
                    if (ar.exception == null) {
                        onDataStateChanged((ArrayList<DataCallResponse>)ar.result);
                    } else {
                        log("DccDefaultState: EVENT_DATA_STATE_CHANGED:" +
                                    " exception; likely radio not available, ignore");
                    }
                    break;
            }
            return HANDLED;
        }

        /**
         * Process the new list of "known" Data Calls
         * @param dcsList as sent by RIL_UNSOL_DATA_CALL_LIST_CHANGED
         */
        private void onDataStateChanged(ArrayList<DataCallResponse> dcsList) {
            final ArrayList<DataConnection> dcListAll;
            final HashMap<Integer, DataConnection> dcListActiveByCid;
            synchronized (mDcListAll) {
                dcListAll = new ArrayList<>(mDcListAll);
                dcListActiveByCid = new HashMap<>(mDcListActiveByCid);
            }

            if (DBG) {
                lr("onDataStateChanged: dcsList=" + dcsList
                        + " dcListActiveByCid=" + dcListActiveByCid);
            }
            if (VDBG) {
                log("onDataStateChanged: mDcListAll=" + dcListAll);
            }

            // Create hashmap of cid to DataCallResponse
            HashMap<Integer, DataCallResponse> dataCallResponseListByCid =
                    new HashMap<Integer, DataCallResponse>();
            for (DataCallResponse dcs : dcsList) {
                dataCallResponseListByCid.put(dcs.getCallId(), dcs);
            }

            // Add a DC that is active but not in the
            // dcsList to the list of DC's to retry
            ArrayList<DataConnection> dcsToRetry = new ArrayList<DataConnection>();
            for (DataConnection dc : dcListActiveByCid.values()) {
                if (dataCallResponseListByCid.get(dc.mCid) == null) {
                    if (DBG) log("onDataStateChanged: add to retry dc=" + dc);
                    dcsToRetry.add(dc);
                }
            }
            if (DBG) log("onDataStateChanged: dcsToRetry=" + dcsToRetry);

            // Find which connections have changed state and send a notification or cleanup
            // and any that are in active need to be retried.
            ArrayList<ApnContext> apnsToCleanup = new ArrayList<ApnContext>();

            boolean isAnyDataCallDormant = false;
            boolean isAnyDataCallActive = false;

            for (DataCallResponse newState : dcsList) {

                DataConnection dc = dcListActiveByCid.get(newState.getCallId());
                if (dc == null) {
                    // UNSOL_DATA_CALL_LIST_CHANGED arrived before SETUP_DATA_CALL completed.
                    loge("onDataStateChanged: no associated DC yet, ignore");
                    continue;
                }

                List<ApnContext> apnContexts = dc.getApnContexts();
                if (apnContexts.size() == 0) {
                    if (DBG) loge("onDataStateChanged: no connected apns, ignore");
                } else {
                    // Determine if the connection/apnContext should be cleaned up
                    // or just a notification should be sent out.
                    if (DBG) {
                        log("onDataStateChanged: Found ConnId=" + newState.getCallId()
                                + " newState=" + newState.toString());
                    }
                    if (newState.getActive() == DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE) {
                        if (mDct.isCleanupRequired.get()) {
                            apnsToCleanup.addAll(apnContexts);
                            mDct.isCleanupRequired.set(false);
                        } else {
                            DcFailCause failCause = DcFailCause.fromInt(newState.getStatus());
                            if (failCause.isRadioRestartFailure(mPhone.getContext(),
                                        mPhone.getSubId())) {
                                if (DBG) {
                                    log("onDataStateChanged: X restart radio, failCause="
                                            + failCause);
                                }
                                mDct.sendRestartRadio();
                            } else if (mDct.isPermanentFailure(failCause)) {
                                if (DBG) {
                                    log("onDataStateChanged: inactive, add to cleanup list. "
                                            + "failCause=" + failCause);
                                }
                                apnsToCleanup.addAll(apnContexts);
                            } else {
                                if (DBG) {
                                    log("onDataStateChanged: inactive, add to retry list. "
                                            + "failCause=" + failCause);
                                }
                                dcsToRetry.add(dc);
                            }
                        }
                    } else {
                        // Its active so update the DataConnections link properties
                        UpdateLinkPropertyResult result = dc.updateLinkProperty(newState);
                        if (result.oldLp.equals(result.newLp)) {
                            if (DBG) log("onDataStateChanged: no change");
                        } else {
                            if (result.oldLp.isIdenticalInterfaceName(result.newLp)) {
                                if (! result.oldLp.isIdenticalDnses(result.newLp) ||
                                        ! result.oldLp.isIdenticalRoutes(result.newLp) ||
                                        ! result.oldLp.isIdenticalHttpProxy(result.newLp) ||
                                        ! result.oldLp.isIdenticalAddresses(result.newLp)) {
                                    // If the same address type was removed and
                                    // added we need to cleanup
                                    CompareResult<LinkAddress> car =
                                        result.oldLp.compareAddresses(result.newLp);
                                    if (DBG) {
                                        log("onDataStateChanged: oldLp=" + result.oldLp +
                                                " newLp=" + result.newLp + " car=" + car);
                                    }
                                    boolean needToClean = false;
                                    for (LinkAddress added : car.added) {
                                        for (LinkAddress removed : car.removed) {
                                            if (NetworkUtils.addressTypeMatches(
                                                    removed.getAddress(),
                                                    added.getAddress())) {
                                                needToClean = true;
                                                break;
                                            }
                                        }
                                    }
                                    if (needToClean) {
                                        if (DBG) {
                                            log("onDataStateChanged: addr change,"
                                                    + " cleanup apns=" + apnContexts
                                                    + " oldLp=" + result.oldLp
                                                    + " newLp=" + result.newLp);
                                        }
                                        apnsToCleanup.addAll(apnContexts);
                                    } else {
                                        if (DBG) log("onDataStateChanged: simple change");

                                        for (ApnContext apnContext : apnContexts) {
                                             mPhone.notifyDataConnection(
                                                 PhoneConstants.REASON_LINK_PROPERTIES_CHANGED,
                                                 apnContext.getApnType());
                                        }
                                    }
                                } else {
                                    if (DBG) {
                                        log("onDataStateChanged: no changes");
                                    }
                                }
                            } else {
                                apnsToCleanup.addAll(apnContexts);
                                if (DBG) {
                                    log("onDataStateChanged: interface change, cleanup apns="
                                            + apnContexts);
                                }
                            }
                        }
                    }
                }

                if (newState.getActive() == DATA_CONNECTION_ACTIVE_PH_LINK_UP) {
                    isAnyDataCallActive = true;
                }
                if (newState.getActive() == DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT) {
                    isAnyDataCallDormant = true;
                }
            }

            if (isAnyDataCallDormant && !isAnyDataCallActive) {
                // There is no way to indicate link activity per APN right now. So
                // Link Activity will be considered dormant only when all data calls
                // are dormant.
                // If a single data call is in dormant state and none of the data
                // calls are active broadcast overall link state as dormant.
                if (DBG) {
                    log("onDataStateChanged: Data Activity updated to DORMANT. stopNetStatePoll");
                }
                mDct.sendStopNetStatPoll(DctConstants.Activity.DORMANT);
            } else {
                if (DBG) {
                    log("onDataStateChanged: Data Activity updated to NONE. " +
                            "isAnyDataCallActive = " + isAnyDataCallActive +
                            " isAnyDataCallDormant = " + isAnyDataCallDormant);
                }
                if (isAnyDataCallActive) {
                    mDct.sendStartNetStatPoll(DctConstants.Activity.NONE);
                }
            }

            if (DBG) {
                lr("onDataStateChanged: dcsToRetry=" + dcsToRetry
                        + " apnsToCleanup=" + apnsToCleanup);
            }

            // Cleanup connections that have changed
            for (ApnContext apnContext : apnsToCleanup) {
                mDct.cleanUpConnection(apnContext);
            }

            // Retry connections that have disappeared
            for (DataConnection dc : dcsToRetry) {
                if (DBG) log("onDataStateChanged: send EVENT_LOST_CONNECTION dc.mTag=" + dc.mTag);
                dc.sendMessage(DataConnection.EVENT_LOST_CONNECTION, dc.mTag);
            }

            if (VDBG) log("onDataStateChanged: X");
        }
    }

    /**
     * lr is short name for logAndAddLogRec
     * @param s
     */
    private void lr(String s) {
        logAndAddLogRec(s);
    }

    @Override
    protected void log(String s) {
        Rlog.d(getName(), s);
    }

    @Override
    protected void loge(String s) {
        Rlog.e(getName(), s);
    }

    /**
     * @return the string for msg.what as our info.
     */
    @Override
    protected String getWhatToString(int what) {
        String info = null;
        info = DataConnection.cmdToString(what);
        return info;
    }

    @Override
    public String toString() {
        synchronized (mDcListAll) {
            return "mDcListAll=" + mDcListAll + " mDcListActiveByCid=" + mDcListActiveByCid;
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        super.dump(fd, pw, args);
        pw.println(" mPhone=" + mPhone);
        synchronized (mDcListAll) {
            pw.println(" mDcListAll=" + mDcListAll);
            pw.println(" mDcListActiveByCid=" + mDcListActiveByCid);
        }
    }
}
