package com.atmob.voiceai.module.clonevoice;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.SeekBar;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.NestedScrollView;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.exoplayer.ExoPlayer;

import com.atmob.app.lib.base.BaseFragment;
import com.atmob.common.logging.AtmobLog;
import com.atmob.common.ui.SizeUtil;
import com.atmob.voiceai.R;
import com.atmob.voiceai.databinding.FragmentCloneVoiceBinding;
import com.atmob.voiceai.dialog.CloneDeleteSureDialog;
import com.atmob.voiceai.dialog.RecordingInstructionsDialog;
import com.atmob.voiceai.utils.ActivityForResultUtil;
import com.atmob.voiceai.utils.AudioRecorder;
import com.atmob.voiceai.utils.ToastUtil;
import com.atmob.voiceai.widget.AudioProgressBar;
import com.gyf.immersionbar.ImmersionBar;

import java.io.IOException;

import dagger.hilt.android.AndroidEntryPoint;

@AndroidEntryPoint
public class CloneVoiceFragment extends BaseFragment<FragmentCloneVoiceBinding> {


    private CloneVoiceViewModel cloneVoiceViewModel;
    private int maxScrollY;
    private ExoPlayer player;
    private CloneDeleteSureDialog cloneDeleteSureDialog;
    private RecordingInstructionsDialog recordingInstructionsDialog;
    private AudioRecorder audioRecorder;

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView();
        initObserver();
    }

    private void initView() {
        initMedia3ExoPlayer();
        initScrollView();
        initSeekBar();
        initPlay();
        binding.progressRecordBar.setOnProgressColorChangeListener(new AudioProgressBar.OnProgressColorChangeListener() {
            @Override
            public void onProgressColorChange(int color) {
                binding.tvRecordStateDesc.setTextColor(color);
            }
        });
    }


    public void showRecordingInstructionsDialog() {
        if (recordingInstructionsDialog == null) {
            recordingInstructionsDialog = new RecordingInstructionsDialog(requireContext());
            recordingInstructionsDialog.setOnRecordingListener(() -> {
                cloneVoiceViewModel.onDialogKnowClick();
            });
        }
        recordingInstructionsDialog.show();
    }

    private void initSeekBar() {
        binding.voiceSeekBar.setProgress(0);
        binding.voiceSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                cloneVoiceViewModel.setCurrentDuration(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                cloneVoiceViewModel.setSeekbarChanging(true);
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                cloneVoiceViewModel.setSeekbarChanging(false);
                player.seekTo(seekBar.getProgress());
            }
        });
    }


    private void initMedia3ExoPlayer() {
        player = new ExoPlayer.Builder(requireContext()).build();
        player.addListener(new Player.Listener() {

            @Override
            public void onPlayerError(PlaybackException error) {
                AtmobLog.d("zk", "onPlayerError: " + error.getMessage());
                ToastUtil.show(R.string.voice_play_error, ToastUtil.LENGTH_SHORT);
                setVoicePlayEnd();
            }

            @Override
            public void onEvents(Player player, Player.Events events) {
                Player.Listener.super.onEvents(player, events);
                if (events.contains(Player.EVENT_IS_LOADING_CHANGED)) {
                    boolean isLoading = player.isLoading();
                    if (!isLoading) {
                        cloneVoiceViewModel.setTotalDuration(player.getDuration());
                        binding.voiceSeekBar.setMax((int) player.getDuration());
                        cloneVoiceViewModel.startMediaTimer();
                    }
                }
            }

            @Override
            public void onPlaybackStateChanged(int state) {
                if (Player.STATE_ENDED == state) {
                    setVoicePlayEnd();
                }
            }
        });
    }

    private void setVoicePlayEnd() {
        player.seekTo(0);
        cloneVoiceViewModel.setCurrentDuration(0);
        player.pause();
        cloneVoiceViewModel.setVoicePlay(false);
    }

    private void initPlay() {
        binding.ivPlay.setOnClickListener(view -> {
            if (player.isLoading()) {
                return;
            }
            if (player.isPlaying()) {
                player.pause();
                cloneVoiceViewModel.setVoicePlay(false);
            } else {
                player.play();
                cloneVoiceViewModel.setVoicePlay(true);
            }
        });
        binding.ivVoiceReduce.setOnClickListener(view -> {
            if (player.isLoading()) {
                return;
            }
            player.seekTo(player.getCurrentPosition() - 5000);
        });
        binding.ivVoiceSpeed.setOnClickListener(view -> {
            if (player.isLoading()) {
                return;
            }
            player.seekTo(player.getCurrentPosition() + 5000);
        });
    }

    private void initScrollView() {
        maxScrollY = (int) SizeUtil.dp2px(60);
        binding.scrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
            if (scrollY > maxScrollY) {
                binding.vStatusBar.setAlpha(1f);
                binding.vMenu.setAlpha(1f);
            } else {
                float alpha = scrollY * 1f / maxScrollY;
                binding.vStatusBar.setAlpha(alpha);
                binding.vMenu.setAlpha(alpha);
            }
        });
    }

    private void initObserver() {
        cloneVoiceViewModel.getStopRecordAudioEvent().observe(getViewLifecycleOwner(), o -> stopRecordAudio());
        cloneVoiceViewModel.getStartRecordAudioEvent().observe(getViewLifecycleOwner(), o -> startRecordAudio());
        cloneVoiceViewModel.getRequestAudioPermission().observe(getViewLifecycleOwner(), o -> requestAudioPermission());
        cloneVoiceViewModel.getShowRecordDialogEvent().observe(getViewLifecycleOwner(), o -> showRecordingInstructionsDialog());
        cloneVoiceViewModel.getDeleteEvent().observe(getViewLifecycleOwner(), id -> {
            if (id == null) {
                return;
            }
            showDeleteSureDialog(id);
        });
        cloneVoiceViewModel.getRefreshAudioCurrentProgress().observe(getViewLifecycleOwner(), o -> {
            long currentPosition = player.getCurrentPosition();
            binding.voiceSeekBar.setProgress((int) currentPosition);
        });
        cloneVoiceViewModel.getUploadVoiceUri().observe(getViewLifecycleOwner(), uri -> {
            if (uri != null) {
                MediaItem mediaItem = MediaItem.fromUri(uri);
                player.setMediaItem(mediaItem);
                player.prepare();
                player.setPlayWhenReady(false);
            } else {
                player.pause();
            }
        });
        cloneVoiceViewModel.getClickLocalUpload().observe(getViewLifecycleOwner(), o -> choiceLocalFile());
    }

    private void startRecordAudio() {
        AtmobLog.d("zk", "startRecordAudio");
        binding.scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                binding.scrollView.fullScroll(NestedScrollView.FOCUS_DOWN);
                binding.scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
        binding.tvRecordExample.startScroll();
        audioRecorder = new AudioRecorder();
        audioRecorder.setMaxDuration(CloneVoiceViewModel.RECORD_AUDIO_MAX_DURATION);
        audioRecorder.setupMediaRecorder(cloneVoiceViewModel.getRecordAudioFilePath());
        try {
            audioRecorder.startRecording();
        } catch (IOException e) {
            ToastUtil.show(e.getMessage(), ToastUtil.LENGTH_SHORT);
        }
    }

    private void stopRecordAudio() {
        binding.tvRecordExample.stopScroll();
        if (audioRecorder != null) {
            audioRecorder.stopRecording();
        }
    }

    private void requestAudioPermission() {
        new ActivityForResultUtil<String, Boolean>().startActivityForResult(requireActivity(), new ActivityResultContracts.RequestPermission(), CloneVoiceViewModel.PERMISSION_AUDIO, result -> {
            if (result) {
                cloneVoiceViewModel.startRecordAudio();
            }
        });
    }

    private void showDeleteSureDialog(int id) {
        if (cloneDeleteSureDialog == null) {
            cloneDeleteSureDialog = new CloneDeleteSureDialog(requireContext());
        }
        cloneDeleteSureDialog.setOnSureClickListener(() -> cloneVoiceViewModel.deleteClone(id));
        cloneDeleteSureDialog.show();
    }

    @Override
    public void onPause() {
        super.onPause();
        cloneVoiceViewModel.setVoicePlay(false);
        if (player != null) {
            player.pause();
        }
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        if (player != null) {
            player.stop();
            player.release();
        }
    }

    private void choiceLocalFile() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("audio/*");
        new ActivityForResultUtil<Intent, ActivityResult>().startActivityForResult(requireActivity(), new ActivityResultContracts.StartActivityForResult(), intent, result -> {
            Uri uri;
            if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null && (uri = result.getData().getData()) != null) {
                cloneVoiceViewModel.setLocalVoiceUri(uri);
            }
        });
    }

    @Override
    protected void configImmersion(@NonNull ImmersionBar immersionBar) {
        super.configImmersion(immersionBar);
        immersionBar.statusBarDarkFont(false);
    }


    @Override
    protected void initViewModel() {
        super.initViewModel();
        cloneVoiceViewModel = getViewModelProvider().get(CloneVoiceViewModel.class);
        binding.setCloneVoiceViewModel(cloneVoiceViewModel);
    }
}
