/*
 * Copyright 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 com.android.managedprovisioning;

import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.widget.TextView;

import com.android.managedprovisioning.model.ProvisioningParams;

import java.io.IOException;
import java.util.concurrent.ExecutionException;

/**
 * Profile owner provisioning sets up a separate profile on a device whose primary user is already
 * set up or being set up.
 *
 * <p>
 * The typical example is setting up a corporate profile that is controlled by their employer on a
 * users personal device to keep personal and work data separate.
 *
 * <p>
 * The activity handles the UI for managed profile provisioning and starts the
 * {@link ProfileOwnerProvisioningService}, which runs through the setup steps in an
 * async task.
 */
public class ProfileOwnerProvisioningActivity extends SetupLayoutActivity {
    protected static final String ACTION_CANCEL_PROVISIONING =
            "com.android.managedprovisioning.CANCEL_PROVISIONING";

    private BroadcastReceiver mServiceMessageReceiver;

    private static final int BROADCAST_TIMEOUT = 2 * 60 * 1000;

    // Provisioning service started
    private static final int STATUS_PROVISIONING = 1;
    // Back button pressed during provisioning, confirm dialog showing.
    private static final int STATUS_CANCEL_CONFIRMING = 2;
    // Cancel confirmed, waiting for the provisioning service to complete.
    private static final int STATUS_CANCELLING = 3;
    // Cancelling not possible anymore, provisioning already finished successfully.
    private static final int STATUS_FINALIZING = 4;

    private static final String KEY_STATUS= "status";
    private static final String KEY_PENDING_INTENT = "pending_intent";

    private int mCancelStatus = STATUS_PROVISIONING;
    private Intent mPendingProvisioningResult = null;
    private ProgressDialog mCancelProgressDialog = null;
    private AccountManager mAccountManager;

    private ProvisioningParams mParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ProvisionLogger.logd("Profile owner provisioning activity ONCREATE");
        mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);

        if (savedInstanceState != null) {
            mCancelStatus = savedInstanceState.getInt(KEY_STATUS, STATUS_PROVISIONING);
            mPendingProvisioningResult = savedInstanceState.getParcelable(KEY_PENDING_INTENT);
        }

        initializeLayoutParams(R.layout.progress, R.string.setting_up_workspace, true);
        setTitle(R.string.setup_profile_progress);

        if (mCancelStatus == STATUS_CANCEL_CONFIRMING) {
            showCancelProvisioningDialog();
        } else if (mCancelStatus == STATUS_CANCELLING) {
            showCancelProgressDialog();
        }
        mParams = (ProvisioningParams) getIntent().getParcelableExtra(
                ProvisioningParams.EXTRA_PROVISIONING_PARAMS);
        if (mParams != null) {
            maybeSetLogoAndMainColor(mParams.mainColor);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Setup broadcast receiver for feedback from service.
        mServiceMessageReceiver = new ServiceMessageReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ProfileOwnerProvisioningService.ACTION_PROVISIONING_SUCCESS);
        filter.addAction(ProfileOwnerProvisioningService.ACTION_PROVISIONING_ERROR);
        filter.addAction(ProfileOwnerProvisioningService.ACTION_PROVISIONING_CANCELLED);
        LocalBroadcastManager.getInstance(this).registerReceiver(mServiceMessageReceiver, filter);

        // Start service async to make sure the UI is loaded first.
        final Handler handler = new Handler(getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(ProfileOwnerProvisioningActivity.this,
                        ProfileOwnerProvisioningService.class);
                intent.putExtras(getIntent());
                startService(intent);
            }
        });
    }

    class ServiceMessageReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mCancelStatus == STATUS_CANCEL_CONFIRMING) {
                // Store the incoming intent and only process it after the user has responded to
                // the cancel dialog
                mPendingProvisioningResult = intent;
                return;
            }
            handleProvisioningResult(intent);
        }
    }

    private void handleProvisioningResult(Intent intent) {
        String action = intent.getAction();
        if (ProfileOwnerProvisioningService.ACTION_PROVISIONING_SUCCESS.equals(action)) {
            if (mCancelStatus == STATUS_CANCELLING) {
                return;
            }

            ProvisionLogger.logd("Successfully provisioned."
                    + "Finishing ProfileOwnerProvisioningActivity");

            onProvisioningSuccess();
        } else if (ProfileOwnerProvisioningService.ACTION_PROVISIONING_ERROR.equals(action)) {
            if (mCancelStatus == STATUS_CANCELLING){
                return;
            }
            String errorLogMessage = intent.getStringExtra(
                    ProfileOwnerProvisioningService.EXTRA_LOG_MESSAGE_KEY);
            ProvisionLogger.logd("Error reported: " + errorLogMessage);
            error(R.string.managed_provisioning_error_text, errorLogMessage);
            // Note that this will be reported as a canceled action
            mCancelStatus = STATUS_FINALIZING;
        } else if (ProfileOwnerProvisioningService.ACTION_PROVISIONING_CANCELLED.equals(action)) {
            if (mCancelStatus != STATUS_CANCELLING) {
                return;
            }
            mCancelProgressDialog.dismiss();
            onProvisioningAborted();
        }
    }

    private void onProvisioningAborted() {
        stopService(new Intent(this, ProfileOwnerProvisioningService.class));
        setResult(Activity.RESULT_CANCELED);
        finish();
    }

    @Override
    public void onBackPressed() {
        if (mCancelStatus == STATUS_PROVISIONING) {
            mCancelStatus = STATUS_CANCEL_CONFIRMING;
            showCancelProvisioningDialog();
        } else {
            super.onBackPressed();
        }
    }

    private void showCancelProvisioningDialog() {
        AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setCancelable(false)
                .setMessage(R.string.profile_owner_cancel_message)
                .setNegativeButton(R.string.profile_owner_cancel_cancel,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int id) {
                                mCancelStatus = STATUS_PROVISIONING;
                                if (mPendingProvisioningResult != null) {
                                    handleProvisioningResult(mPendingProvisioningResult);
                                }
                            }
                        })
                .setPositiveButton(R.string.profile_owner_cancel_ok,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int id) {
                                confirmCancel();
                            }
                        })
                .create();
        alertDialog.show();
    }

    protected void showCancelProgressDialog() {
        mCancelProgressDialog = new ProgressDialog(this);
        mCancelProgressDialog.setMessage(getText(R.string.profile_owner_cancelling));
        mCancelProgressDialog.setCancelable(false);
        mCancelProgressDialog.setCanceledOnTouchOutside(false);
        mCancelProgressDialog.show();
    }

    public void error(int resourceId, String logText) {
        ProvisionLogger.loge(logText);
        new AlertDialog.Builder(this)
                .setTitle(R.string.provisioning_error_title)
                .setMessage(resourceId)
                .setCancelable(false)
                .setPositiveButton(R.string.device_owner_error_ok,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int id) {
                                onProvisioningAborted();
                            }
                        })
                .show();
    }

    private void confirmCancel() {
        if (mCancelStatus != STATUS_CANCEL_CONFIRMING) {
            // Can only cancel if provisioning hasn't finished at this point.
            return;
        }
        mCancelStatus = STATUS_CANCELLING;
        Intent intent = new Intent(ProfileOwnerProvisioningActivity.this,
                ProfileOwnerProvisioningService.class);
        intent.setAction(ACTION_CANCEL_PROVISIONING);
        startService(intent);
        showCancelProgressDialog();
    }

    /**
     * Finish activity and stop service.
     */
    private void onProvisioningSuccess() {
        mCancelStatus = STATUS_FINALIZING;
        stopService(new Intent(this, ProfileOwnerProvisioningService.class));
        setResult(Activity.RESULT_OK);
        finish();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt(KEY_STATUS, mCancelStatus);
        outState.putParcelable(KEY_PENDING_INTENT, mPendingProvisioningResult);
    }

    @Override
    public void onPause() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceMessageReceiver);
        super.onPause();
    }
}
