/*
 * Copyright (C) 2017 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 libcore.tzdata.prototype_updater;

import android.app.timezone.Callback;
import android.app.timezone.DistroFormatVersion;
import android.app.timezone.DistroRulesVersion;
import android.app.timezone.RulesManager;
import android.app.timezone.RulesState;
import android.app.timezone.RulesUpdaterContract;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.ParcelFileDescriptor;
import android.provider.TimeZoneRulesDataContract;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import libcore.io.Streams;

// TODO(nfuller): Prevent multiple broadcasts being handled at once?
// TODO(nfuller): Improve logging
// TODO(nfuller): Make the rules check async?
// TODO(nfuller): Need async generally for SystemService calls from BroadcastReceiver?
public class RulesCheckReceiver extends BroadcastReceiver {
    final static String TAG = "RulesCheckReceiver";

    private RulesManager mRulesManager;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (!RulesUpdaterContract.ACTION_TRIGGER_RULES_UPDATE_CHECK.equals(intent.getAction())) {
            // Unknown. Do nothing.
            Log.w(TAG, "Unrecognized intent action received: " + intent
                    + ", action=" + intent.getAction());
            return;
        }

        mRulesManager = (RulesManager) context.getSystemService("timezone");

        byte[] token = intent.getByteArrayExtra(RulesUpdaterContract.EXTRA_CHECK_TOKEN);

        // Note: We rely on the system server to check that the configured data application is the
        // one that exposes the content provider with the well-known authority, and is a privileged
        // application as required. It is *not* checked here and it is assumed the updater can trust
        // the data application.

        // Obtain the information about what the data app is telling us to do.
        String operation = getOperation(context);
        if (operation == null) {
            // TODO Log
            boolean success = true; // No point in retrying.
            handleCheckComplete(token, success);
            return;
        }
        switch (operation) {
            case TimeZoneRulesDataContract.OPERATION_NO_OP:
                // TODO Log
                // No-op. Just acknowledge the check.
                handleCheckComplete(token, true /* success */);
                break;
            case TimeZoneRulesDataContract.OPERATION_UNINSTALL:
                // TODO Log
                handleUninstall(token);
                break;
            case TimeZoneRulesDataContract.OPERATION_INSTALL:
                // TODO Log
                DistroVersionInfo distroVersionInfo = getDistroVersionInfo(context);
                handleCopyAndInstall(context, token, distroVersionInfo);
                break;
            default:
                // TODO Log
                final boolean success = true; // No point in retrying.
                handleCheckComplete(token, success);
        }
    }

    private String getOperation(Context context) {
        Cursor cursor = context.getContentResolver()
                .query(TimeZoneRulesDataContract.OPERATION_URI,
                        new String[] { TimeZoneRulesDataContract.COLUMN_OPERATION },
                        null /* selection */, null /* selectionArgs */, null /* sortOrder */);
        if (cursor == null) {
            Log.e(TAG, "getOperation: query returned null");
            return null;
        }
        if (!cursor.moveToFirst()) {
            Log.e(TAG, "getOperation: query returned empty results");
            return null;
        }

        try {
            return cursor.getString(0);
        } catch (Exception e) {
            Log.e(TAG, "getOperation: getString() threw an exception", e);
            return null;
        }
    }

    private DistroVersionInfo getDistroVersionInfo(Context context) {
        Cursor cursor = context.getContentResolver()
                .query(TimeZoneRulesDataContract.OPERATION_URI,
                        new String[] {
                                TimeZoneRulesDataContract.COLUMN_DISTRO_MAJOR_VERSION,
                                TimeZoneRulesDataContract.COLUMN_DISTRO_MINOR_VERSION,
                                TimeZoneRulesDataContract.COLUMN_RULES_VERSION,
                                TimeZoneRulesDataContract.COLUMN_REVISION},
                        null /* selection */, null /* selectionArgs */, null /* sortOrder */);
        if (cursor == null) {
            Log.e(TAG, "getDistroVersionInfo: query returned null");
            return null;
        }
        if (!cursor.moveToFirst()) {
            Log.e(TAG, "getDistroVersionInfo: query returned empty results");
            return null;
        }

        try {
            return new DistroVersionInfo(
                    cursor.getInt(0),
                    cursor.getInt(1),
                    cursor.getString(2),
                    cursor.getInt(3));
        } catch (Exception e) {
            Log.e(TAG, "getDistroVersionInfo: getInt()/getString() threw an exception", e);
            return null;
        }
    }

    private void handleCopyAndInstall(Context context, byte[] checkToken,
            DistroVersionInfo distroVersionInfo) {

        // Decide whether to proceed with the install.
        RulesState rulesState = mRulesManager.getRulesState();
        if (!(rulesState.isDistroFormatVersionSupported(distroVersionInfo.mDistroFormatVersion)
            && rulesState.isSystemVersionOlderThan(distroVersionInfo.mDistroRulesVersion))) {
            // Nothing to do.
            handleCheckComplete(checkToken, true /* success */);
            return;
        }

        // Copy the data locally before passing it on....security and whatnot.
        // TODO(nfuller): Need to do the copy here?
        File file = copyDataToLocalFile(context);
        if (file == null) {
            // It's possible this may get better if the problem is related to storage space.
            boolean success = false;
            handleCheckComplete(checkToken, success);
            return;
        }
        handleInstall(checkToken, file);
    }

    private static File copyDataToLocalFile(Context context) {
        File extractedFile = new File(context.getFilesDir(), "temp.zip");
        ParcelFileDescriptor fileDescriptor;
        try {
            fileDescriptor = context.getContentResolver().openFileDescriptor(
                    TimeZoneRulesDataContract.DATA_URI, "r");
            if (fileDescriptor == null) {
                throw new FileNotFoundException("ContentProvider returned null");
            }
        } catch (FileNotFoundException e) {
            Log.e(TAG, "copyDataToLocalFile: Unable to open file descriptor"
                    + TimeZoneRulesDataContract.DATA_URI, e);
            return null;
        }

        try (ParcelFileDescriptor pfd = fileDescriptor;
             InputStream fis = new FileInputStream(pfd.getFileDescriptor());
             FileOutputStream fos = new FileOutputStream(extractedFile, false /* append */)) {
            Streams.copy(fis, fos);
        } catch (IOException e) {
            Log.e(TAG, "Unable to create asset storage file: " + extractedFile, e);
            return null;
        }
        return extractedFile;
    }

    private void handleInstall(final byte[] checkToken, final File contentFile) {
        // Convert the distroFile to a ParcelFileDescriptor.
        final ParcelFileDescriptor distroFileDescriptor;
        try {
            distroFileDescriptor =
                    ParcelFileDescriptor.open(contentFile, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Unable to create ParcelFileDescriptor from " + contentFile);
            handleCheckComplete(checkToken, false /* success */);
            return;
        }

        Callback callback = new Callback() {
            @Override
            public void onFinished(int status) {
                Log.i(TAG, "onFinished: Finished install: " + status);

                // TODO(nfuller): Can this be closed sooner?
                try {
                    distroFileDescriptor.close();
                } catch (IOException e) {
                    Log.e(TAG, "Unable to close ParcelFileDescriptor for " + contentFile, e);
                } finally {
                    // Delete the file we no longer need.
                    contentFile.delete();
                }
            }
        };

        try {
            int requestStatus =
                    mRulesManager.requestInstall(distroFileDescriptor, checkToken, callback);
            Log.i(TAG, "handleInstall: Request sent:" + requestStatus);
        } catch (Exception e) {
            Log.e(TAG, "handleInstall: Error", e);
        }
    }

    private void handleUninstall(byte[] checkToken) {
        Callback callback = new Callback() {
            @Override
            public void onFinished(int status) {
                Log.i(TAG, "onFinished: Finished uninstall: " + status);
            }
        };

        try {
            int requestStatus =
                    mRulesManager.requestUninstall(checkToken, callback);
            Log.i(TAG, "handleUninstall: Request sent" + requestStatus);
        } catch (Exception e) {
            Log.e(TAG, "handleUninstall: Error", e);
        }
    }

    private void handleCheckComplete(final byte[] token, final boolean success) {
        try {
            mRulesManager.requestNothing(token, success);
            Log.i(TAG, "doInBackground: Called checkComplete: token="
                    + Arrays.toString(token) + ", success=" + success);
        } catch (Exception e) {
            Log.e(TAG, "doInBackground: Error calling checkComplete()", e);
        }
    }

    private static class DistroVersionInfo {

        final DistroFormatVersion mDistroFormatVersion;
        final DistroRulesVersion mDistroRulesVersion;

        DistroVersionInfo(int distroMajorVersion, int distroMinorVersion,
                String rulesVersion, int revision) {
            mDistroFormatVersion = new DistroFormatVersion(distroMajorVersion, distroMinorVersion);
            mDistroRulesVersion = new DistroRulesVersion(rulesVersion, revision);
        }
    }
}
