package com.lemenzo.gallery.privacy;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.net.Uri;

import com.lemenzo.gallery.editor.BitmapBudget;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;

/** Creates a metadata-free share copy without changing the original. */
public final class PrivateShare {
    private PrivateShare() {}

    public static Uri create(Context context, Uri source, String mimeType) throws IOException {
        File root = new File(context.getCacheDir(), "private_share");
        if (!root.exists() && !root.mkdirs()) throw new IOException("Cannot create private share cache");
        cleanup(root);

        String mime = mimeType == null ? "" : mimeType.toLowerCase(Locale.ROOT);
        if (mime.contains("jpeg") || mime.contains("jpg")) {
            String name = "Lemenzo_private_" + System.currentTimeMillis() + ".jpg";
            File out = new File(root, name);
            try (InputStream in = context.getContentResolver().openInputStream(source);
                 OutputStream stream = new FileOutputStream(out)) {
                if (in == null) throw new IOException("Cannot open source image");
                JpegSanitizer.sanitize(in, stream);
            } catch (IOException failure) {
                out.delete();
                throw failure;
            }
            return contentUri(name);
        }

        // Formats whose metadata cannot be safely stripped container-wise with platform APIs
        // are decoded and freshly encoded. The decode is memory-budgeted to avoid OOM.
        final int[] sourceSize = new int[2];
        ImageDecoder.Source decoderSource = ImageDecoder.createSource(context.getContentResolver(), source);
        Bitmap bitmap = ImageDecoder.decodeBitmap(decoderSource, (decoder, info, src) -> {
            int width = info.getSize().getWidth();
            int height = info.getSize().getHeight();
            sourceSize[0] = width; sourceSize[1] = height;
            int maxEdge = BitmapBudget.safeDecodeMaxEdge(width, height);
            if (maxEdge > 0 && Math.max(width, height) > maxEdge) {
                float scale = maxEdge / (float)Math.max(width, height);
                decoder.setTargetSize(Math.max(1, Math.round(width * scale)), Math.max(1, Math.round(height * scale)));
            }
            decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            decoder.setMutableRequired(false);
        });
        boolean alpha = bitmap.hasAlpha();
        Bitmap.CompressFormat format;
        String extension;
        int quality;
        if (alpha || mime.contains("png")) {
            format = Bitmap.CompressFormat.PNG; extension = ".png"; quality = 100;
        } else if (mime.contains("webp")) {
            format = Bitmap.CompressFormat.WEBP_LOSSLESS; extension = ".webp"; quality = 100;
        } else {
            format = Bitmap.CompressFormat.JPEG; extension = ".jpg"; quality = 97;
        }
        String name = "Lemenzo_private_" + System.currentTimeMillis() + extension;
        File out = new File(root, name);
        try (FileOutputStream stream = new FileOutputStream(out)) {
            if (!bitmap.compress(format, quality, stream)) throw new IOException("Encoding failed");
        } finally { bitmap.recycle(); }
        return contentUri(name);
    }

    private static Uri contentUri(String name) {
        return new Uri.Builder().scheme("content").authority(PrivateShareProvider.AUTHORITY).appendPath(name).build();
    }

    private static void cleanup(File root) {
        long cutoff = System.currentTimeMillis() - 60L * 60L * 1000L;
        File[] files = root.listFiles();
        if (files == null) return;
        for (File file : files) if (file.lastModified() < cutoff) file.delete();
    }
}
