package com.m2sdl.undercooked;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RenderEffect;
import android.graphics.Shader;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.FileOutputStream;

public class FilterActivity extends AppCompatActivity implements SensorEventListener {

    private ImageView imageView;
    private Button validateButton;
    private Button shakeFilter;
    private Button deepfryFilter;

    private String photoPath;
    private Bitmap bitmap;

    private SensorManager sensorManager;
    private Sensor accelerometer;

    private MediaRecorder mediaRecorder;
    private Handler audioHandler = new Handler();
    private boolean isRecording = false;

    private boolean shakeEnabled = false;
    private long lastShake = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_filter);

        imageView = findViewById(R.id.imageViewFilter);
        validateButton = findViewById(R.id.validateFilter);
        shakeFilter = findViewById(R.id.filterShake);
        deepfryFilter = findViewById(R.id.filterDeepFry);

        photoPath = getIntent().getStringExtra("photoUri");
        bitmap = BitmapFactory.decodeFile(photoPath);
        imageView.setImageBitmap(bitmap);

        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        shakeFilter.setOnClickListener(v -> {
            shakeEnabled = true;
            Toast.makeText(this, "Secouez le téléphone pour flouter", Toast.LENGTH_LONG).show();
        });

        deepfryFilter.setOnClickListener(v -> {
            shakeEnabled = false;
            startListening();
            Toast.makeText(this, "Criez dans le téléphone pour deepfry", Toast.LENGTH_LONG).show();
        });

        validateButton.setOnClickListener(v -> {
            saveBitmap();
            Intent result = new Intent();
            result.putExtra("photoUri", photoPath);
            setResult(RESULT_OK, result);
            finish();
        });

        if (checkSelfPermission(android.Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{android.Manifest.permission.RECORD_AUDIO}, 200);
        }
    }

    private void saveBitmap() {
        try {
            File file = new File(photoPath);
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // SHAKE FILTER

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
        if (mediaRecorder != null) {
            try {
                mediaRecorder.stop();
                mediaRecorder.release();
            } catch (Exception ignored) {}
            mediaRecorder = null;
        }

        isRecording = false;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (!shakeEnabled) return;

        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        float accel = (float) Math.sqrt(x*x + y*y + z*z);

        if (accel > 15f) {

            long now = System.currentTimeMillis();
            if (now - lastShake < 1000) return;
            lastShake = now;

            applyBlur();
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}

    private void applyBlur() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            imageView.setRenderEffect(RenderEffect.createBlurEffect(10f, 10f, Shader.TileMode.CLAMP));
        } else {
            Toast.makeText(this, "Version d'Android inférieure à 12, l'effet ne fonctionnera pas.", Toast.LENGTH_LONG).show();
        }
    }

    // DEEP FRY FILTER

    private void startListening() {
        try {
            mediaRecorder = new MediaRecorder();
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mediaRecorder.setOutputFile(getCacheDir() + "/temp.3gp");
            mediaRecorder.prepare();
            mediaRecorder.start();

            isRecording = true;
            monitorAudio();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void monitorAudio() {
        audioHandler.postDelayed(new Runnable() {
            @Override
            public void run() {

                if (!isRecording || mediaRecorder == null) return;

                int amplitude = mediaRecorder.getMaxAmplitude();

                int noiseThreshold = 6000;

                float intensity = 0f;

                if (amplitude > noiseThreshold) {

                    float adjusted = amplitude - noiseThreshold;

                    intensity = Math.min(adjusted / 8000f, 3f);
                }

                if (intensity > 0f) {
                    applyDeepFry(intensity);
                }

                audioHandler.postDelayed(this, 200);
            }
        }, 200);
    }

    private void applyDeepFry(float intensity) {

        Bitmap fried = bitmap.copy(bitmap.getConfig(), true);

        ColorMatrix matrix = getColorMatrix(intensity);

        Paint paint = new Paint();
        paint.setColorFilter(new ColorMatrixColorFilter(matrix));

        Canvas canvas = new Canvas(fried);
        canvas.drawBitmap(fried, 0, 0, paint);

        imageView.setImageBitmap(fried);
        bitmap = fried;
    }

    @NonNull
    private static ColorMatrix getColorMatrix(float intensity) {
        float saturation = 1f + intensity * 2f;
        float contrast = 1f + intensity;

        ColorMatrix matrix = new ColorMatrix();

        // Saturation
        matrix.setSaturation(saturation);

        ColorMatrix contrastMatrix = new ColorMatrix(new float[]{
                contrast, 0, 0, 0, 30 * intensity,
                0, contrast, 0, 0, -20 * intensity,
                0, 0, contrast, 0, -20 * intensity,
                0, 0, 0, 1, 0
        });

        matrix.postConcat(contrastMatrix);
        return matrix;
    }
}
