package com.lemenzo.gallery.editor;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;

/** Local color adjustments. No network, ML service, or cloud dependency. */
public final class ImageAdjustments {
    public static final int FILTER_NONE = 0;
    public static final int FILTER_VIVID = 1;
    public static final int FILTER_MONO = 2;
    public static final int FILTER_COOL = 3;
    public static final int FILTER_WARM = 4;

    private ImageAdjustments() {}

    public static Bitmap apply(Bitmap source, float brightness, float contrast,
            float saturation, float warmth, float exposure, float tint, int filter) {
        if (source == null) throw new IllegalArgumentException("source == null");
        Bitmap result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
        result.setHasAlpha(source.hasAlpha());
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
        paint.setColorFilter(createColorFilter(brightness, contrast, saturation, warmth, exposure, tint, filter));
        canvas.drawBitmap(source, 0f, 0f, paint);
        return result;
    }

    public static ColorMatrixColorFilter createColorFilter(float brightness, float contrast,
            float saturation, float warmth, float exposure, float tint, int filter) {
        ColorMatrix combined = new ColorMatrix();

        float exposureScale = (float) Math.pow(2.0, clamp(exposure));
        float c = Math.max(0.1f, 1f + clamp(contrast));
        float translate = 128f * (1f - c) + clamp(brightness) * 255f;
        ColorMatrix contrastBrightnessExposure = new ColorMatrix(new float[] {
                c * exposureScale, 0, 0, 0, translate,
                0, c * exposureScale, 0, 0, translate,
                0, 0, c * exposureScale, 0, translate,
                0, 0, 0, 1, 0
        });
        combined.postConcat(contrastBrightnessExposure);

        ColorMatrix sat = new ColorMatrix();
        sat.setSaturation(Math.max(0f, Math.min(2.5f, saturation)));
        combined.postConcat(sat);

        float w = clamp(warmth) * 28f;
        float t = clamp(tint) * 24f;
        ColorMatrix temperatureTint = new ColorMatrix(new float[] {
                1, 0, 0, 0, w + t,
                0, 1, 0, 0, -Math.abs(t) * .30f,
                0, 0, 1, 0, -w + t,
                0, 0, 0, 1, 0
        });
        combined.postConcat(temperatureTint);

        if (filter == FILTER_VIVID) {
            ColorMatrix vivid = new ColorMatrix();
            vivid.setSaturation(1.28f);
            combined.postConcat(vivid);
        } else if (filter == FILTER_MONO) {
            ColorMatrix mono = new ColorMatrix();
            mono.setSaturation(0f);
            combined.postConcat(mono);
        } else if (filter == FILTER_COOL) {
            combined.postConcat(new ColorMatrix(new float[] {
                    .96f,0,0,0,-4, 0,1,0,0,0, 0,0,1.06f,0,8, 0,0,0,1,0
            }));
        } else if (filter == FILTER_WARM) {
            combined.postConcat(new ColorMatrix(new float[] {
                    1.06f,0,0,0,8, 0,1,0,0,2, 0,0,.95f,0,-4, 0,0,0,1,0
            }));
        }
        return new ColorMatrixColorFilter(combined);
    }

    private static float clamp(float value) { return Math.max(-1f, Math.min(1f, value)); }
}
