/*
 * Copyright (C) 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 com.example.android.systemupdatersample;

import android.content.Context;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
import android.util.Log;

import com.example.android.systemupdatersample.services.PrepareStreamingService;
import com.example.android.systemupdatersample.util.PayloadSpecs;
import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
import com.example.android.systemupdatersample.util.UpdateEngineProperties;
import com.google.common.util.concurrent.AtomicDouble;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;

/**
 * Manages the update flow. Asynchronously interacts with the {@link UpdateEngine}.
 */
public class UpdateManager {

    private static final String TAG = "UpdateManager";

    /** HTTP Header: User-Agent; it will be sent to the server when streaming the payload. */
    private static final String HTTP_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";

    private final UpdateEngine mUpdateEngine;
    private final PayloadSpecs mPayloadSpecs;

    private AtomicInteger mUpdateEngineStatus =
            new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE);
    private AtomicInteger mEngineErrorCode = new AtomicInteger(UpdateEngineErrorCodes.UNKNOWN);
    private AtomicDouble mProgress = new AtomicDouble(0);

    private final UpdateManager.UpdateEngineCallbackImpl
            mUpdateEngineCallback = new UpdateManager.UpdateEngineCallbackImpl();

    private PayloadSpec mLastPayloadSpec;
    private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);

    private IntConsumer mOnEngineStatusUpdateCallback = null;
    private DoubleConsumer mOnProgressUpdateCallback = null;
    private IntConsumer mOnEngineCompleteCallback = null;

    private final Object mLock = new Object();

    public UpdateManager(UpdateEngine updateEngine, PayloadSpecs payloadSpecs) {
        this.mUpdateEngine = updateEngine;
        this.mPayloadSpecs = payloadSpecs;
    }

    /**
     * Binds to {@link UpdateEngine}.
     */
    public void bind() {
        this.mUpdateEngine.bind(mUpdateEngineCallback);
    }

    /**
     * Unbinds from {@link UpdateEngine}.
     */
    public void unbind() {
        this.mUpdateEngine.unbind();
    }

    /**
     * @return a number from {@code 0.0} to {@code 1.0}.
     */
    public float getProgress() {
        return (float) this.mProgress.get();
    }

    /**
     * Returns true if manual switching slot is required. Value depends on
     * the update config {@code ab_config.force_switch_slot}.
     */
    public boolean manualSwitchSlotRequired() {
        return mManualSwitchSlotRequired.get();
    }

    /**
     * Sets update engine status update callback. Value of {@code status} will
     * be one of the values from {@link UpdateEngine.UpdateStatusConstants}.
     *
     * @param onStatusUpdateCallback a callback with parameter {@code status}.
     */
    public void setOnEngineStatusUpdateCallback(IntConsumer onStatusUpdateCallback) {
        synchronized (mLock) {
            this.mOnEngineStatusUpdateCallback = onStatusUpdateCallback;
        }
    }

    private Optional<IntConsumer> getOnEngineStatusUpdateCallback() {
        synchronized (mLock) {
            return mOnEngineStatusUpdateCallback == null
                    ? Optional.empty()
                    : Optional.of(mOnEngineStatusUpdateCallback);
        }
    }

    /**
     * Sets update engine payload application complete callback. Value of {@code errorCode} will
     * be one of the values from {@link UpdateEngine.ErrorCodeConstants}.
     *
     * @param onComplete a callback with parameter {@code errorCode}.
     */
    public void setOnEngineCompleteCallback(IntConsumer onComplete) {
        synchronized (mLock) {
            this.mOnEngineCompleteCallback = onComplete;
        }
    }

    private Optional<IntConsumer> getOnEngineCompleteCallback() {
        synchronized (mLock) {
            return mOnEngineCompleteCallback == null
                    ? Optional.empty()
                    : Optional.of(mOnEngineCompleteCallback);
        }
    }

    /**
     * Sets progress update callback. Progress is a number from {@code 0.0} to {@code 1.0}.
     *
     * @param onProgressCallback a callback with parameter {@code progress}.
     */
    public void setOnProgressUpdateCallback(DoubleConsumer onProgressCallback) {
        synchronized (mLock) {
            this.mOnProgressUpdateCallback = onProgressCallback;
        }
    }

    private Optional<DoubleConsumer> getOnProgressUpdateCallback() {
        synchronized (mLock) {
            return mOnProgressUpdateCallback == null
                    ? Optional.empty()
                    : Optional.of(mOnProgressUpdateCallback);
        }
    }

    /**
     * Requests update engine to stop any ongoing update. If an update has been applied,
     * leave it as is.
     *
     * <p>Sometimes it's possible that the
     * update engine would throw an error when the method is called, and the only way to
     * handle it is to catch the exception.</p>
     */
    public void cancelRunningUpdate() {
        try {
            mUpdateEngine.cancel();
        } catch (Exception e) {
            Log.w(TAG, "UpdateEngine failed to stop the ongoing update", e);
        }
    }

    /**
     * Resets update engine to IDLE state. If an update has been applied it reverts it.
     *
     * <p>Sometimes it's possible that the
     * update engine would throw an error when the method is called, and the only way to
     * handle it is to catch the exception.</p>
     */
    public void resetUpdate() {
        try {
            mUpdateEngine.resetStatus();
        } catch (Exception e) {
            Log.w(TAG, "UpdateEngine failed to reset the update", e);
        }
    }

    /**
     * Applies the given update.
     *
     * <p>UpdateEngine works asynchronously. This method doesn't wait until
     * end of the update.</p>
     */
    public void applyUpdate(Context context, UpdateConfig config) {
        mEngineErrorCode.set(UpdateEngineErrorCodes.UNKNOWN);

        if (!config.getAbConfig().getForceSwitchSlot()) {
            mManualSwitchSlotRequired.set(true);
        } else {
            mManualSwitchSlotRequired.set(false);
        }

        if (config.getInstallType() == UpdateConfig.AB_INSTALL_TYPE_NON_STREAMING) {
            applyAbNonStreamingUpdate(config);
        } else {
            applyAbStreamingUpdate(context, config);
        }
    }

    private void applyAbNonStreamingUpdate(UpdateConfig config) {
        List<String> extraProperties = prepareExtraProperties(config);

        PayloadSpec payload;
        try {
            payload = mPayloadSpecs.forNonStreaming(config.getUpdatePackageFile());
        } catch (IOException e) {
            Log.e(TAG, "Error creating payload spec", e);
            return;
        }
        updateEngineApplyPayload(payload, extraProperties);
    }

    private void applyAbStreamingUpdate(Context context, UpdateConfig config) {
        List<String> extraProperties = prepareExtraProperties(config);

        Log.d(TAG, "Starting PrepareStreamingService");
        PrepareStreamingService.startService(context, config, (code, payloadSpec) -> {
            if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) {
                extraProperties.add("USER_AGENT=" + HTTP_USER_AGENT);
                config.getStreamingMetadata()
                        .getAuthorization()
                        .ifPresent(s -> extraProperties.add("AUTHORIZATION=" + s));
                updateEngineApplyPayload(payloadSpec, extraProperties);
            } else {
                Log.e(TAG, "PrepareStreamingService failed, result code is " + code);
            }
        });
    }

    private List<String> prepareExtraProperties(UpdateConfig config) {
        List<String> extraProperties = new ArrayList<>();

        if (!config.getAbConfig().getForceSwitchSlot()) {
            // Disable switch slot on reboot, which is enabled by default.
            // User will enable it manually by clicking "Switch Slot" button on the screen.
            extraProperties.add(UpdateEngineProperties.PROPERTY_DISABLE_SWITCH_SLOT_ON_REBOOT);
        }
        return extraProperties;
    }

    /**
     * Applies given payload.
     *
     * <p>UpdateEngine works asynchronously. This method doesn't wait until
     * end of the update.</p>
     *
     * <p>It's possible that the update engine throws a generic error, such as upon seeing invalid
     * payload properties (which come from OTA packages), or failing to set up the network
     * with the given id.</p>
     *
     * @param payloadSpec contains url, offset and size to {@code PAYLOAD_BINARY_FILE_NAME}
     * @param extraProperties additional properties to pass to {@link UpdateEngine#applyPayload}
     */
    private void updateEngineApplyPayload(PayloadSpec payloadSpec, List<String> extraProperties) {
        mLastPayloadSpec = payloadSpec;

        ArrayList<String> properties = new ArrayList<>(payloadSpec.getProperties());
        if (extraProperties != null) {
            properties.addAll(extraProperties);
        }
        try {
            mUpdateEngine.applyPayload(
                    payloadSpec.getUrl(),
                    payloadSpec.getOffset(),
                    payloadSpec.getSize(),
                    properties.toArray(new String[0]));
        } catch (Exception e) {
            Log.e(TAG, "UpdateEngine failed to apply the update", e);
        }
    }

    /**
     * Sets the new slot that has the updated partitions as the active slot,
     * which device will boot into next time.
     * This method is only supposed to be called after the payload is applied.
     *
     * Invoking {@link UpdateEngine#applyPayload} with the same payload url, offset, size
     * and payload metadata headers doesn't trigger new update. It can be used to just switch
     * active A/B slot.
     *
     * {@link UpdateEngine#applyPayload} might take several seconds to finish, and it will
     * invoke callbacks {@link this#onStatusUpdate} and {@link this#onPayloadApplicationComplete)}.
     */
    public void setSwitchSlotOnReboot() {
        Log.d(TAG, "setSwitchSlotOnReboot invoked");
        List<String> extraProperties = new ArrayList<>();
        // PROPERTY_SKIP_POST_INSTALL should be passed on to skip post-installation hooks.
        extraProperties.add(UpdateEngineProperties.PROPERTY_SKIP_POST_INSTALL);
        // It sets property SWITCH_SLOT_ON_REBOOT=1 by default.
        // HTTP headers are not required, UpdateEngine is not expected to stream payload.
        updateEngineApplyPayload(mLastPayloadSpec, extraProperties);
    }

    private void onStatusUpdate(int status, float progress) {
        int previousStatus = mUpdateEngineStatus.get();
        mUpdateEngineStatus.set(status);
        mProgress.set(progress);

        getOnProgressUpdateCallback().ifPresent(callback -> callback.accept(progress));

        if (previousStatus != status) {
            getOnEngineStatusUpdateCallback().ifPresent(callback -> callback.accept(status));
        }
    }

    private void onPayloadApplicationComplete(int errorCode) {
        Log.d(TAG, "onPayloadApplicationComplete invoked, errorCode=" + errorCode);
        mEngineErrorCode.set(errorCode);

        getOnEngineCompleteCallback()
                .ifPresent(callback -> callback.accept(errorCode));
    }

    /**
     * Helper class to delegate {@code update_engine} callbacks to UpdateManager
     */
    class UpdateEngineCallbackImpl extends UpdateEngineCallback {
        @Override
        public void onStatusUpdate(int status, float percent) {
            UpdateManager.this.onStatusUpdate(status, percent);
        }

        @Override
        public void onPayloadApplicationComplete(int errorCode) {
            UpdateManager.this.onPayloadApplicationComplete(errorCode);
        }
    }

}
