/*
 * Copyright 2018 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.app.servertransaction;

import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESTART;
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;

import android.app.Activity;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.util.IntArray;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

/**
 * Helper class for {@link TransactionExecutor} that contains utils for lifecycle path resolution.
 * @hide
 */
public class TransactionExecutorHelper {
    // A penalty applied to path with destruction when looking for the shortest one.
    private static final int DESTRUCTION_PENALTY = 10;

    private static final int[] ON_RESUME_PRE_EXCUTION_STATES = new int[] { ON_START, ON_PAUSE };

    // Temp holder for lifecycle path.
    // No direct transition between two states should take more than one complete cycle of 6 states.
    @ActivityLifecycleItem.LifecycleState
    private IntArray mLifecycleSequence = new IntArray(6);

    /**
     * Calculate the path through main lifecycle states for an activity and fill
     * @link #mLifecycleSequence} with values starting with the state that follows the initial
     * state.
     * <p>NOTE: The returned value is used internally in this class and is not a copy. It's contents
     * may change after calling other methods of this class.</p>
     */
    @VisibleForTesting
    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
        if (start == UNDEFINED || finish == UNDEFINED) {
            throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
        }
        if (start == ON_RESTART || finish == ON_RESTART) {
            throw new IllegalArgumentException(
                    "Can't start or finish in intermittent RESTART state");
        }
        if (finish == PRE_ON_CREATE && start != finish) {
            throw new IllegalArgumentException("Can only start in pre-onCreate state");
        }

        mLifecycleSequence.clear();
        if (finish >= start) {
            if (start == ON_START && finish == ON_STOP) {
                // A case when we from start to stop state soon, we don't need to go
                // through the resumed, paused state.
                mLifecycleSequence.add(ON_STOP);
            } else {
                // just go there
                for (int i = start + 1; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            }
        } else { // finish < start, can't just cycle down
            if (start == ON_PAUSE && finish == ON_RESUME) {
                // Special case when we can just directly go to resumed state.
                mLifecycleSequence.add(ON_RESUME);
            } else if (start <= ON_STOP && finish >= ON_START) {
                // Restart and go to required state.

                // Go to stopped state first.
                for (int i = start + 1; i <= ON_STOP; i++) {
                    mLifecycleSequence.add(i);
                }
                // Restart
                mLifecycleSequence.add(ON_RESTART);
                // Go to required state
                for (int i = ON_START; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            } else {
                // Relaunch and go to required state

                // Go to destroyed state first.
                for (int i = start + 1; i <= ON_DESTROY; i++) {
                    mLifecycleSequence.add(i);
                }
                // Go to required state
                for (int i = ON_CREATE; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            }
        }

        // Remove last transition in case we want to perform it with some specific params.
        if (excludeLastState && mLifecycleSequence.size() != 0) {
            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
        }

        return mLifecycleSequence;
    }

    /**
     * Pick a state that goes before provided post-execution state and would require the least
     * lifecycle transitions to get to.
     * It will also make sure to try avoiding a path with activity destruction and relaunch if
     * possible.
     * @param r An activity that we're trying to resolve the transition for.
     * @param postExecutionState Post execution state to compute for.
     * @return One of states that precede the provided post-execution state, or
     *         {@link ActivityLifecycleItem#UNDEFINED} if there is not path.
     */
    @VisibleForTesting
    public int getClosestPreExecutionState(ActivityClientRecord r,
            int postExecutionState) {
        switch (postExecutionState) {
            case UNDEFINED:
                return UNDEFINED;
            case ON_RESUME:
                return getClosestOfStates(r, ON_RESUME_PRE_EXCUTION_STATES);
            default:
                throw new UnsupportedOperationException("Pre-execution states for state: "
                        + postExecutionState + " is not supported.");
        }
    }

    /**
     * Pick a state that would require the least lifecycle transitions to get to.
     * It will also make sure to try avoiding a path with activity destruction and relaunch if
     * possible.
     * @param r An activity that we're trying to resolve the transition for.
     * @param finalStates An array of valid final states.
     * @return One of the provided final states, or {@link ActivityLifecycleItem#UNDEFINED} if none
     *         were provided or there is not path.
     */
    @VisibleForTesting
    public int getClosestOfStates(ActivityClientRecord r, int[] finalStates) {
        if (finalStates == null || finalStates.length == 0) {
            return UNDEFINED;
        }

        final int currentState = r.getLifecycleState();
        int closestState = UNDEFINED;
        for (int i = 0, shortestPath = Integer.MAX_VALUE, pathLength; i < finalStates.length; i++) {
            getLifecyclePath(currentState, finalStates[i], false /* excludeLastState */);
            pathLength = mLifecycleSequence.size();
            if (pathInvolvesDestruction(mLifecycleSequence)) {
                pathLength += DESTRUCTION_PENALTY;
            }
            if (shortestPath > pathLength) {
                shortestPath = pathLength;
                closestState = finalStates[i];
            }
        }
        return closestState;
    }

    /** Get the lifecycle state request to match the current state in the end of a transaction. */
    public static ActivityLifecycleItem getLifecycleRequestForCurrentState(ActivityClientRecord r) {
        final int prevState = r.getLifecycleState();
        final ActivityLifecycleItem lifecycleItem;
        switch (prevState) {
            // TODO(lifecycler): Extend to support all possible states.
            case ON_PAUSE:
                lifecycleItem = PauseActivityItem.obtain();
                break;
            case ON_STOP:
                lifecycleItem = StopActivityItem.obtain(0 /* configChanges */);
                break;
            default:
                lifecycleItem = ResumeActivityItem.obtain(false /* isForward */);
                break;
        }

        return lifecycleItem;
    }

    /**
     * Check if there is a destruction involved in the path. We want to avoid a lifecycle sequence
     * that involves destruction and recreation if there is another path.
     */
    private static boolean pathInvolvesDestruction(IntArray lifecycleSequence) {
        final int size = lifecycleSequence.size();
        for (int i = 0; i < size; i++) {
            if (lifecycleSequence.get(i) == ON_DESTROY) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return the index of the last callback that requests the state in which activity will be after
     * execution. If there is a group of callbacks in the end that requests the same specific state
     * or doesn't request any - we will find the first one from such group.
     *
     * E.g. ActivityResult requests RESUMED post-execution state, Configuration does not request any
     * specific state. If there is a sequence
     *   Configuration - ActivityResult - Configuration - ActivityResult
     * index 1 will be returned, because ActivityResult request on position 1 will be the last
     * request that moves activity to the RESUMED state where it will eventually end.
     */
    static int lastCallbackRequestingState(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        if (callbacks == null || callbacks.size() == 0) {
            return -1;
        }

        // Go from the back of the list to front, look for the request closes to the beginning that
        // requests the state in which activity will end after all callbacks are executed.
        int lastRequestedState = UNDEFINED;
        int lastRequestingCallback = -1;
        for (int i = callbacks.size() - 1; i >= 0; i--) {
            final ClientTransactionItem callback = callbacks.get(i);
            final int postExecutionState = callback.getPostExecutionState();
            if (postExecutionState != UNDEFINED) {
                // Found a callback that requests some post-execution state.
                if (lastRequestedState == UNDEFINED || lastRequestedState == postExecutionState) {
                    // It's either a first-from-end callback that requests state or it requests
                    // the same state as the last one. In both cases, we will use it as the new
                    // candidate.
                    lastRequestedState = postExecutionState;
                    lastRequestingCallback = i;
                } else {
                    break;
                }
            }
        }

        return lastRequestingCallback;
    }

    /** Dump transaction to string. */
    static String transactionToString(ClientTransaction transaction,
            ClientTransactionHandler transactionHandler) {
        final StringWriter stringWriter = new StringWriter();
        final PrintWriter pw = new PrintWriter(stringWriter);
        final String prefix = tId(transaction);
        transaction.dump(prefix, pw);
        pw.append(prefix + "Target activity: ")
                .println(getActivityName(transaction.getActivityToken(), transactionHandler));
        return stringWriter.toString();
    }

    /** @return A string in format "tId:<transaction hashcode> ". */
    static String tId(ClientTransaction transaction) {
        return "tId:" + transaction.hashCode() + " ";
    }

    /** Get activity string name for provided token. */
    static String getActivityName(IBinder token, ClientTransactionHandler transactionHandler) {
        final Activity activity = getActivityForToken(token, transactionHandler);
        if (activity != null) {
            return activity.getComponentName().getClassName();
        }
        return "Not found for token: " + token;
    }

    /** Get short activity class name for provided token. */
    static String getShortActivityName(IBinder token, ClientTransactionHandler transactionHandler) {
        final Activity activity = getActivityForToken(token, transactionHandler);
        if (activity != null) {
            return activity.getComponentName().getShortClassName();
        }
        return "Not found for token: " + token;
    }

    private static Activity getActivityForToken(IBinder token,
            ClientTransactionHandler transactionHandler) {
        if (token == null) {
            return null;
        }
        return transactionHandler.getActivity(token);
    }

    /** Get lifecycle state string name. */
    static String getStateName(int state) {
        switch (state) {
            case UNDEFINED:
                return "UNDEFINED";
            case PRE_ON_CREATE:
                return "PRE_ON_CREATE";
            case ON_CREATE:
                return "ON_CREATE";
            case ON_START:
                return "ON_START";
            case ON_RESUME:
                return "ON_RESUME";
            case ON_PAUSE:
                return "ON_PAUSE";
            case ON_STOP:
                return "ON_STOP";
            case ON_DESTROY:
                return "ON_DESTROY";
            case ON_RESTART:
                return "ON_RESTART";
            default:
                throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
        }
    }
}
