package com.lemenzo.messenger.mms;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Telephony;
import android.telephony.SubscriptionManager;
import android.util.Log;
import com.google.android.mms.MmsException;
import com.google.android.mms.pdu.GenericPdu;
import com.google.android.mms.pdu.RetrieveConf;
import com.lemenzo.messenger.data.ContactResolver;
import com.lemenzo.messenger.data.MessageRepository;
import com.lemenzo.messenger.notifications.MessageNotificationManager;
import com.lemenzo.messenger.util.ReceiverAsync;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public final class MmsDownloadResultReceiver extends BroadcastReceiver {
    public static final String ACTION_MMS_DOWNLOADED = "com.lemenzo.messenger.MMS_DOWNLOADED";
    private static final String TAG = "LemenzoMessengerMms";

    @Override public void onReceive(Context context, Intent intent) {
        final String raw = intent.getStringExtra("content_uri");
        final String token = intent.getStringExtra("download_token");
        if (raw == null || token == null) return;
        final int resultCode = getResultCode();
        final int subId = intent.getIntExtra(
                "subscription_id", SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        final Context appContext = context.getApplicationContext();
        ReceiverAsync.run(this, () -> finishDownload(appContext, raw, token, subId, resultCode));
    }

    private static void finishDownload(
            Context context, String raw, String token, int subId, int resultCode) {
        Uri contentUri = Uri.parse(raw);
        MmsDownloadStore store = new MmsDownloadStore(context);

        try {
            if (resultCode != Activity.RESULT_OK) {
                Log.w(TAG, "MMS download failed: " + resultCode);
                store.markFailed(token);
                MessageNotificationManager.notifyMmsDownloadFailed(context, token);
                return;
            }

            File file = MmsFileProvider.fileFor(context, contentUri);
            byte[] data = readFully(file);
            GenericPdu parsed = MmsPduUtils.parse(data);
            if (!(parsed instanceof RetrieveConf)) {
                store.markFailed(token);
                MessageNotificationManager.notifyMmsDownloadFailed(context, token);
                return;
            }

            RetrieveConf conf = (RetrieveConf) parsed;
            Uri persisted = MmsPduUtils.persistIncoming(context, conf);
            if (persisted == null) {
                store.markFailed(token);
                MessageNotificationManager.notifyMmsDownloadFailed(context, token);
                return;
            }

            android.content.ContentValues values = new android.content.ContentValues();
            values.put(Telephony.Mms.SUBSCRIPTION_ID, subId);
            values.put(Telephony.Mms.READ, 0);
            values.put(Telephony.Mms.SEEN, 0);
            try { context.getContentResolver().update(persisted, values, null, null); }
            catch (RuntimeException ignored) {}

            store.remove(token);
            MessageNotificationManager.cancelMmsDownloadFailure(context, token);

            MessageRepository repo = new MessageRepository(context);
            long threadId = repo.threadIdForMms(persisted);
            String sender = MmsPduUtils.sender(conf);
            String text = MmsPduUtils.text(conf);
            String subject = MmsPduUtils.subject(conf);
            String snippet = !text.isEmpty() ? text : (!subject.isEmpty() ? subject
                    : context.getString(com.lemenzo.messenger.R.string.mms_attachment));

            MessageNotificationManager.notifyIncoming(context, threadId, sender, subId,
                    new ContactResolver(context).displayName(sender), snippet,
                    (persisted.toString() + System.currentTimeMillis()).hashCode());
        } catch (IOException | MmsException | RuntimeException e) {
            store.markFailed(token);
            MessageNotificationManager.notifyMmsDownloadFailed(context, token);
            Log.e(TAG, "Unable to finalize downloaded MMS", e);
        } finally {
            MmsFileProvider.delete(context, contentUri);
        }
    }

    private static byte[] readFully(File file) throws IOException {
        long length = file.length();
        if (length <= 0 || length > 20L * 1024L * 1024L) throw new IOException("Invalid MMS PDU size");
        byte[] out = new byte[(int) length];
        try (FileInputStream in = new FileInputStream(file)) {
            int offset = 0;
            while (offset < out.length) {
                int n = in.read(out, offset, out.length - offset);
                if (n < 0) break;
                offset += n;
            }
            if (offset != out.length) throw new IOException("Short MMS PDU read");
        }
        return out;
    }
}
