/*
 * Copyright (C) 2015 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.tv.settings.device.storage;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.leanback.app.GuidedStepSupportFragment;
import androidx.leanback.widget.GuidanceStylist;
import androidx.leanback.widget.GuidedAction;

import com.android.tv.settings.R;
import com.android.tv.settings.dialog.ProgressDialogFragment;

import java.io.File;
import java.util.List;
import java.util.Objects;

public class MigrateStorageActivity extends FragmentActivity {
    private static final String TAG = "MigrateStorageActivity";

    private static final String EXTRA_MIGRATE_HERE =
            "com.android.tv.settings.device.storage.MigrateStorageActivity.MIGRATE_HERE";

    private static final String SAVE_STATE_MOVE_ID = "MigrateStorageActivity.MOVE_ID";

    private VolumeInfo mTargetVolumeInfo;
    private VolumeInfo mVolumeInfo;
    private String mTargetVolumeDesc;
    private String mVolumeDesc;
    private int mMoveId = -1;
    private final Handler mHandler = new Handler();
    private PackageManager mPackageManager;
    private final PackageManager.MoveCallback mMoveCallback = new PackageManager.MoveCallback() {
        @Override
        public void onStatusChanged(int moveId, int status, long estMillis) {
            if (moveId != mMoveId || !PackageManager.isMoveStatusFinished(status)) {
                return;
            }
            if (status == PackageManager.MOVE_SUCCEEDED) {
                showMigrationSuccessToast();
            } else {
                showMigrationFailureToast();
            }
            finish();
        }
    };

    public static Intent getLaunchIntent(Context context, String volumeId,
            boolean migrateHere) {
        final Intent i = new Intent(context, MigrateStorageActivity.class);
        i.putExtra(VolumeInfo.EXTRA_VOLUME_ID, volumeId);
        i.putExtra(EXTRA_MIGRATE_HERE, migrateHere);
        return i;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        final String volumeId = intent.getStringExtra(VolumeInfo.EXTRA_VOLUME_ID);
        final StorageManager storageManager = getSystemService(StorageManager.class);

        if (intent.getBooleanExtra(EXTRA_MIGRATE_HERE, true)) {
            mTargetVolumeInfo = storageManager.findVolumeById(volumeId);
            if (mTargetVolumeInfo == null) {
                finish();
                return;
            }
            mTargetVolumeDesc = storageManager.getBestVolumeDescription(mTargetVolumeInfo);
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content,
                            MigrateConfirmationStepFragment.newInstance(mTargetVolumeDesc))
                    .commitAllowingStateLoss();
        } else {
            mVolumeInfo = storageManager.findVolumeById(volumeId);
            if (mVolumeInfo == null) {
                finish();
                return;
            }
            mVolumeDesc = storageManager.getBestVolumeDescription(mVolumeInfo);
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content,
                            ChooseStorageStepFragment.newInstance(mVolumeInfo))
                    .commitAllowingStateLoss();
        }

        mPackageManager = getPackageManager();
        mPackageManager.registerMoveCallback(mMoveCallback, mHandler);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(SAVE_STATE_MOVE_ID, mMoveId);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getPackageManager().unregisterMoveCallback(mMoveCallback);
    }

    private void onConfirmCancel() {
        finish();
    }

    private void onConfirmProceed() {
        startMigrationInternal();
    }

    private void onChoose(VolumeInfo volumeInfo) {
        mTargetVolumeInfo = volumeInfo;
        final StorageManager storageManager = getSystemService(StorageManager.class);
        mTargetVolumeDesc = storageManager.getBestVolumeDescription(mTargetVolumeInfo);
        startMigrationInternal();
    }

    private void startMigrationInternal() {
        try {
            mMoveId = mPackageManager.movePrimaryStorage(mTargetVolumeInfo);
            getSupportFragmentManager().beginTransaction()
                    .replace(android.R.id.content,
                            MigrateProgressFragment.newInstance(mTargetVolumeDesc))
                    .commitNowAllowingStateLoss();
        } catch (IllegalArgumentException e) {
            // This will generally happen if there's a move already in progress or completed
            StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);

            if (Objects.equals(mTargetVolumeInfo.getFsUuid(),
                    sm.getPrimaryStorageVolume().getUuid())) {
                // The data is already on the target volume
                showMigrationSuccessToast();
            } else {
                // The data is most likely in the process of being moved
                Log.e(TAG, "Storage migration failure", e);
                showMigrationFailureToast();
            }
            finish();
        } catch (IllegalStateException e) {
            showMigrationFailureToast();
            finish();
        }
    }

    private void showMigrationSuccessToast() {
        Toast.makeText(this,
                getString(R.string.storage_wizard_migrate_toast_success, mTargetVolumeDesc),
                Toast.LENGTH_SHORT).show();
    }

    private void showMigrationFailureToast() {
        Toast.makeText(this,
                getString(R.string.storage_wizard_migrate_toast_failure, mTargetVolumeDesc),
                Toast.LENGTH_SHORT).show();
    }

    public static class MigrateConfirmationStepFragment extends GuidedStepSupportFragment {
        private static final String ARG_VOLUME_DESC = "volumeDesc";

        private static final int ACTION_CONFIRM = 1;
        private static final int ACTION_LATER = 2;

        public static MigrateConfirmationStepFragment newInstance(String volumeDescription) {
            final MigrateConfirmationStepFragment fragment = new MigrateConfirmationStepFragment();
            final Bundle b = new Bundle(1);
            b.putString(ARG_VOLUME_DESC, volumeDescription);
            fragment.setArguments(b);
            return fragment;
        }

        @NonNull
        @Override
        public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
            final String driveDesc = getArguments().getString(ARG_VOLUME_DESC);
            return new GuidanceStylist.Guidance(
                    getString(R.string.storage_wizard_migrate_confirm_title, driveDesc),
                    getString(R.string.storage_wizard_migrate_confirm_description, driveDesc),
                    null,
                    getActivity().getDrawable(R.drawable.ic_storage_132dp));
        }

        @Override
        public void onCreateActions(@NonNull List<GuidedAction> actions,
                Bundle savedInstanceState) {
            actions.add(new GuidedAction.Builder(getContext())
                    .id(ACTION_CONFIRM)
                    .title(R.string.storage_wizard_migrate_confirm_action_move_now)
                    .build());
            actions.add(new GuidedAction.Builder(getContext())
                    .id(ACTION_LATER)
                    .title(R.string.storage_wizard_migrate_confirm_action_move_later)
                    .build());
        }

        @Override
        public void onGuidedActionClicked(GuidedAction action) {
            final int id = (int) action.getId();
            switch (id) {
                case ACTION_CONFIRM:
                    ((MigrateStorageActivity) getActivity()).onConfirmProceed();
                    break;
                case ACTION_LATER:
                    ((MigrateStorageActivity) getActivity()).onConfirmCancel();
                    break;
            }
        }
    }

    public static class ChooseStorageStepFragment extends GuidedStepSupportFragment {

        private List<VolumeInfo> mCandidateVolumes;

        public static ChooseStorageStepFragment newInstance(VolumeInfo currentVolumeInfo) {
            Bundle args = new Bundle(1);
            args.putString(VolumeInfo.EXTRA_VOLUME_ID, currentVolumeInfo.getId());

            ChooseStorageStepFragment fragment = new ChooseStorageStepFragment();
            fragment.setArguments(args);
            return fragment;
        }

        @NonNull
        @Override
        public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
            return new GuidanceStylist.Guidance(
                    getString(R.string.storage_wizard_migrate_choose_title),
                    null,
                    null,
                    getActivity().getDrawable(R.drawable.ic_storage_132dp));
        }

        @Override
        public void onCreateActions(@NonNull List<GuidedAction> actions,
                Bundle savedInstanceState) {
            final StorageManager storageManager =
                    getContext().getSystemService(StorageManager.class);
            mCandidateVolumes =
                    getContext().getPackageManager().getPrimaryStorageCandidateVolumes();
            final String volumeId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
            for (final VolumeInfo candidate : mCandidateVolumes) {
                if (TextUtils.equals(candidate.getId(), volumeId)) {
                    continue;
                }
                final File path = candidate.getPath();
                final String avail = Formatter.formatFileSize(getActivity(), path.getFreeSpace());
                actions.add(new GuidedAction.Builder(getContext())
                        .title(storageManager.getBestVolumeDescription(candidate))
                        .description(getString(
                                R.string.storage_wizard_back_up_apps_space_available, avail))
                        .id(mCandidateVolumes.indexOf(candidate))
                        .build());
            }

        }

        @Override
        public void onGuidedActionClicked(GuidedAction action) {
            final VolumeInfo volumeInfo = mCandidateVolumes.get((int) action.getId());
            ((MigrateStorageActivity)getActivity()).onChoose(volumeInfo);
        }
    }

    public static class MigrateProgressFragment extends ProgressDialogFragment {
        private static final String ARG_VOLUME_DESC = "volumeDesc";

        public static MigrateProgressFragment newInstance(String volumeDescription) {
            final MigrateProgressFragment fragment = new MigrateProgressFragment();
            final Bundle b = new Bundle(1);
            b.putString(ARG_VOLUME_DESC, volumeDescription);
            fragment.setArguments(b);
            return fragment;
        }

        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            setTitle(getActivity().getString(R.string.storage_wizard_migrate_progress_title,
                    getArguments().getString(ARG_VOLUME_DESC)));
            setSummary(getActivity()
                    .getString(R.string.storage_wizard_migrate_progress_description));
        }

    }
}
