package com.ar.imagetracear.activity;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;


import com.ar.imagetracear.R;
import com.ar.imagetracear.databinding.ActivityImagetraceBinding;
import com.ar.imagetracear.topon.AdManager;
import com.ar.imagetracear.topon.onActionListener;
import com.ar.imagetracear.utils.DisplayUtils;
import com.ar.imagetracear.utils.ImageLoader;
import com.ar.imagetracear.utils.ImagePositioner;
import com.ar.imagetracear.utils.RequestUtils;
import com.ar.imagetracear.utils.TouchEventHandler;
import com.google.common.util.concurrent.ListenableFuture;

public class ImageTraceActivity extends AppCompatActivity {
    private ActivityImagetraceBinding viewBinding;
    private ImageView imageView;
    private Bitmap bitmap;
    private Camera camera;
    private ImageCapture capture;
    private boolean isFlashOn = false;
    private boolean isMirror = false;

    private static final int PERMISSION_CAMERA = 100;
    private static final int PERMISSION_STORAGE = 101;

    private final ActivityResultLauncher<Intent> imageChooserLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            outcome -> {
                if (outcome.getResultCode() == RESULT_OK && outcome.getData() != null) {
                    Uri selectedImageUri = outcome.getData().getData();
                    if (selectedImageUri != null) {
                        imageView.setImageURI(selectedImageUri);
                    }
                }
            });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        EdgeToEdge.enable(this);

        bindView();

        View mainLayout = findViewById(R.id.main);
        ViewCompat.setOnApplyWindowInsetsListener(mainLayout, (view, windowInsets) -> {
            Insets bars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
            view.setPadding(bars.left, bars.top, bars.right, bars.bottom);
            return windowInsets;
        });

        AdManager.loadAllAd();
        AdManager.showTopOn(this, new onActionListener() {
            @Override
            public void onAction() {

            }
        });

        configureTouchHandler();
        setupUiInteractions();
        checkIncomingIntent();
        checkAndInitCamera();
    }

    private void bindView() {
        viewBinding = ActivityImagetraceBinding.inflate(getLayoutInflater());
        setContentView(viewBinding.getRoot());
        imageView = viewBinding.imageFull;
    }

    @SuppressLint("ClickableViewAccessibility")
    private void configureTouchHandler() {
        imageView.setOnTouchListener((v, motionEvent) ->
                TouchEventHandler.handleImageTouchEvent((ImageView) v, motionEvent)
        );
    }

    private void setupUiInteractions() {
        viewBinding.seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            public void onProgressChanged(SeekBar bar, int value, boolean user) {
                imageView.setAlpha((100 - value) / 100f);
            }

            public void onStartTrackingTouch(SeekBar bar) {
            }

            public void onStopTrackingTouch(SeekBar bar) {
            }
        });

        viewBinding.importImage.setOnClickListener(v -> {
            AdManager.showTopOn(this, new onActionListener() {
                @Override
                public void onAction() {
                    openImageChooser();
                }
            });
        });
        viewBinding.light.setOnClickListener(v -> toggleFlash());
        viewBinding.back.setOnClickListener(v -> {
            AdManager.showTopOn(this, new onActionListener() {
                @Override
                public void onAction() {
                    finish();
                }
            });
        });
        viewBinding.reversal.setOnClickListener(v -> mirrorImage());
        viewBinding.fabCapture.setOnClickListener(v -> takeSnapshot());
    }

    private void checkIncomingIntent() {
        String pathFromIntent = getIntent().getStringExtra("imagePath");
        if (pathFromIntent != null) {
            displayImage(pathFromIntent);
        }
    }

    private void checkAndInitCamera() {
        String[] perms = RequestUtils.getCameraPermissions();
        if (RequestUtils.hasRequests(this, perms)) {
            prepareCamera();
        } else {
            RequestUtils.requestPermissions(this, perms, PERMISSION_CAMERA);
        }
    }

    private void prepareCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider provider = cameraProviderFuture.get();
                activateCamera(provider);
            } catch (Exception ex) {
                Toast.makeText(this, "Camera failed to start", Toast.LENGTH_SHORT).show();
            }
        }, ContextCompat.getMainExecutor(this));
    }

    private void activateCamera(ProcessCameraProvider provider) {
        Preview cameraPreview = new Preview.Builder().build();
        CameraSelector selector = CameraSelector.DEFAULT_BACK_CAMERA;
        capture = new ImageCapture.Builder().build();

        cameraPreview.setSurfaceProvider(viewBinding.preview.getSurfaceProvider());
        provider.unbindAll();
        camera = provider.bindToLifecycle(this, selector, cameraPreview, capture);

        if (bitmap != null) {
            ImagePositioner.centerBitmapInImageView(imageView, bitmap, DisplayUtils.getDeviceScreenSize(this));
        }
    }

    private void takeSnapshot() {
        if (capture == null) {
            Toast.makeText(this, "Camera not initialized", Toast.LENGTH_SHORT).show();
            return;
        }

        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, "img_" + System.currentTimeMillis() + ".jpg");
        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);

        ImageCapture.OutputFileOptions fileOptions = new ImageCapture.OutputFileOptions.Builder(
                getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values).build();

        capture.takePicture(fileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
            public void onImageSaved(@NonNull ImageCapture.OutputFileResults result) {
                Toast.makeText(ImageTraceActivity.this, "Photo saved", Toast.LENGTH_SHORT).show();
            }

            public void onError(@NonNull ImageCaptureException exception) {
                Toast.makeText(ImageTraceActivity.this, "Error: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void toggleFlash() {
        if (camera != null) {
            isFlashOn = !isFlashOn;
            camera.getCameraControl().enableTorch(isFlashOn);
            viewBinding.light.setImageResource(isFlashOn ? R.drawable.flash_on : R.drawable.flash_off);
        }
    }

    private void mirrorImage() {
        isMirror = !isMirror;
        imageView.setScaleX(isMirror ? -1f : 1f);
        viewBinding.reversal.setImageResource(isMirror ? R.drawable.reversal_on : R.drawable.reversal_off);
    }

    private void openImageChooser() {
        String[] permissions = RequestUtils.getCameraPermissions();
        if (RequestUtils.hasRequests(this, permissions)) {
            Intent chooser = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            imageChooserLauncher.launch(chooser);
        } else {
            RequestUtils.requestPermissions(this, permissions, PERMISSION_STORAGE);
        }
    }

    private void displayImage(String filePath) {
        bitmap = filePath.startsWith("/data/user/")
                ? ImageLoader.loadBitmapFromFile(filePath)
                : ImageLoader.loadBitmapFromAppAssets(this, filePath);

        if (bitmap != null) {
            ImageLoader.displayBitmapInView(imageView, bitmap);
        } else {
            Toast.makeText(this, "Failed to load image", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int code, @NonNull String[] perms, @NonNull int[] results) {
        super.onRequestPermissionsResult(code, perms, results);
        if (RequestUtils.handlePermissionsResult(results)) {
            if (code == PERMISSION_CAMERA) {
                prepareCamera();
            } else if (code == PERMISSION_STORAGE) {
                openImageChooser();
            }
        } else {
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        viewBinding = null;
    }
}