package com.daya.live_teaching.ui.fragmnet;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.GridView;
import android.widget.TextView;

import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;

import com.cooleshow.base.ui.fragment.BaseFragment;
import com.cooleshow.base.utils.FileUtils;
import com.cooleshow.base.utils.LogUtils;
import com.daya.live_teaching.R;
import com.daya.live_teaching.common.ResultCallback;
import com.daya.live_teaching.databinding.FragmentPlayMetronomeBinding;
import com.daya.live_teaching.model.ClassMember;
import com.daya.live_teaching.model.DownLoadSong;
import com.daya.live_teaching.model.PlayMidi;
import com.daya.live_teaching.model.Role;
import com.daya.live_teaching.model.UserInfo;
import com.daya.live_teaching.repository.UserRepository;
import com.daya.live_teaching.rtc.RtcManager;
import com.daya.live_teaching.ui.adapter.MetronomeAdapter;
import com.daya.live_teaching.viewmodel.ClassViewModel;

import java.io.File;
import java.util.List;

import cn.rongcloud.rtc.api.RCRTCAudioMixer;
import cn.rongcloud.rtc.api.RCRTCConfig;
import cn.rongcloud.rtc.api.RCRTCEngine;
import cn.rongcloud.rtc.api.stream.RCRTCAudioStreamConfig;
import cn.rongcloud.rtc.base.RCRTCParamsType;
import io.rong.imkit.RongIM;
import io.rong.imlib.RongIMClient;


public class PlayMetronomeFragment extends BaseFragment<FragmentPlayMetronomeBinding> {

    TextView tvTick;
    TextView tvTock;
    GridView recyclerView;
    private ClassViewModel classViewModel;
    private int timerPeriod = 5 * 1000;
    private SoundPool mSoundPool;
    private boolean playSound = true;
    public int PlayMidiNumber = 0;
    private Runnable playMteronomeRunnable;
    SoundPool soundPool;
    private int tickVoiceId;
    private int tockVoiceId;
    private Handler handler;
    private String roomId;
    private MetronomeAdapter adapter;
    public UserInfo userInfo;
    boolean isPlaySound;
    boolean isPlayMusic;

    @Override
    protected FragmentPlayMetronomeBinding getLayoutView() {
        return FragmentPlayMetronomeBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void initView(View rootView) {
        tvTick = mViewBinding.tvTick;
        tvTock = mViewBinding.tvTock;
        recyclerView = mViewBinding.recyclerView;
        mteronomeSoundPool();
    }

    @Override
    protected void initData() {

        classViewModel = ViewModelProviders.of(getActivity()).get(ClassViewModel.class);
        classViewModel.getRoomId().observe(this, s -> roomId = s);
        classViewModel.getPlayMidiMode().observe(this, new Observer<PlayMidi>() {
            @Override
            public void onChanged(PlayMidi playMidi) {
                RCRTCAudioMixer.getInstance().stop();
                playMetronome(playMidi, true);
            }
        });
        adapter = new MetronomeAdapter(getContext());
        recyclerView.setNumColumns(4);
        recyclerView.setAdapter(adapter);
        classViewModel.getLeaveRoom().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                RCRTCAudioMixer.getInstance().stop();
                isPlayMusic = false;
                isPlaySound = false;
                PlayMidiNumber = 0;
                if (playMteronomeRunnable != null) {
                    handler.removeCallbacks(playMteronomeRunnable);
                    handler = null;
                    playMteronomeRunnable = null;
                    soundPool.stop(tickVoiceId);
                    soundPool.stop(tockVoiceId);
                }
                isSubscribeAudio(false);
                setAudioScenrio(false, false);
            }
        });
        userInfo = classViewModel.getUserInfo().getValue();
        classViewModel.getUserInfo().observe(this, new Observer<UserInfo>() {
            @Override
            public void onChanged(UserInfo user) {
                userInfo = user;
            }
        });
        // 自己用户信息
        classViewModel.getPlayExamSong().observe(this, new Observer<ClassMember.ScheduleStudentMusicScoresBean>() {
            @Override
            public void onChanged(ClassMember.ScheduleStudentMusicScoresBean musicScoresBean) {
                if (musicScoresBean.getPlayStatus() == 1) {
                    DownloadSong(musicScoresBean.getMusicScoreAccompanimentId(), musicScoresBean.getUrl(), musicScoresBean.getMp3Url(), true);
                }
                if (musicScoresBean.getAccompanimentPlayStatus() == 1) {
                    DownloadMp3Song(musicScoresBean.getMusicScoreAccompanimentId(), musicScoresBean.getMp3Url(), true);
                }
                if (musicScoresBean.getPlayStatus() == 0 && musicScoresBean.getAccompanimentPlayStatus() == 0) {
                    playAccompaniment(musicScoresBean.getUrl(), false);
                }
            }
        });

        classViewModel.getDownLoadSong().observe(this, new Observer<DownLoadSong>() {
            @Override
            public void onChanged(DownLoadSong song) {
                DownloadSong(song.getMusicScoreAccompanimentId(), song.getUrl(), song.getMp3Url(), false);
            }
        });

        if (userInfo != null && userInfo.getRole() == Role.STUDENT && null != userInfo.getScheduleStudentMusicScores() && userInfo.getScheduleStudentMusicScores().size() > 0) {
            classViewModel.getLocalUserStartVideoChat().observe(this, new Observer<Boolean>() {
                @Override
                public void onChanged(Boolean aBoolean) {
                    if (aBoolean) {
                        setAudioScenrio(false, false);
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                classViewModel.adjustExamSong(roomId, null, 0);//同步
                                if (userInfo != null && userInfo.getPlayMidiJson() != null && userInfo.getPlayMidiJson().isEnable()) {
                                    ClassMember.PlayMidiJsonBean playMidiJsonBean = userInfo.getPlayMidiJson();
                                    playMetronome(new PlayMidi(playMidiJsonBean.isEnable(), playMidiJsonBean.getRate(), playMidiJsonBean.getCustomType(), playMidiJsonBean.getPlayVolume()), true);
                                    return;
                                }

                                for (ClassMember.ScheduleStudentMusicScoresBean musicScoresBean : userInfo.getScheduleStudentMusicScores()) {
                                    if (musicScoresBean.getPlayStatus() == 1) {
                                        DownloadSong(musicScoresBean.getMusicScoreAccompanimentId(), musicScoresBean.getUrl(), musicScoresBean.getMp3Url(), true);
                                        break;
                                    }
                                    if (musicScoresBean.getAccompanimentPlayStatus() == 1) {
                                        DownloadMp3Song(musicScoresBean.getMusicScoreAccompanimentId(), musicScoresBean.getMp3Url(), true);
                                        break;
                                    }
                                }
                            }
                        }, 2000);
                    }
                }
            });

        }
    }

    private void DownloadSong(String musicScoreAccompanimentId, String url, String mp3Url, boolean enable) {
        if (TextUtils.isEmpty(url) && TextUtils.isEmpty(mp3Url)) {
            return;
        }
        if (TextUtils.isEmpty(url) && !TextUtils.isEmpty(mp3Url)) {
            DownloadMp3Song(musicScoreAccompanimentId, mp3Url, enable);
            return;
        }
        String filePath = FileUtils.getCacheDir(getContext(), FileUtils.examDownloadDirectory);
        String fileName = url.substring(url.lastIndexOf("/") + 1);


        if (!FileUtils.isFileExist(filePath + File.separator + fileName)) {
            classViewModel.downLoadFile(url, filePath, fileName, new ResultCallback<Boolean>() {
                @Override
                public void onSuccess(Boolean aBoolean) {
                    if (!TextUtils.isEmpty(mp3Url)) {
                        DownloadMp3Song(musicScoreAccompanimentId, mp3Url, false);
                    } else {
                        classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, aBoolean ? 1 : 2);
                    }
                    if (enable) {
                        playAccompaniment(url, enable);
                    }
                }

                @Override
                public void onFail(int errorCode, String errorStr) {
                    classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, 2);
                }
            });
        } else {
            if (enable) {
                playAccompaniment(url, enable);
            }
            classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, 1);
        }
    }

    private void DownloadMp3Song(String musicScoreAccompanimentId, String mp3Url, boolean enable) {
        if (TextUtils.isEmpty(mp3Url)) {
            return;
        }
        String filePath = FileUtils.getCacheDir(getContext(), FileUtils.examDownloadDirectory);
        String fileName = mp3Url.substring(mp3Url.lastIndexOf("/") + 1);
        if (FileUtils.isFileExist(filePath + File.separator + fileName)) {
            if (enable) {
                playAccompaniment(mp3Url, enable);
            }
            classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, 1);
        } else {
            classViewModel.downLoadFile(mp3Url, filePath, fileName, new ResultCallback<Boolean>() {
                @Override
                public void onSuccess(Boolean aBoolean) {
                    classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, aBoolean ? 1 : 2);
                    if (enable)
                        playAccompaniment(mp3Url, enable);
                }

                @Override
                public void onFail(int errorCode, String errorStr) {
                    classViewModel.adjustExamSong(roomId, musicScoreAccompanimentId, 2);
                }
            });
        }
    }

    private void playAccompaniment(String url, boolean isEnable) {
        isPlayMusic = isEnable;
        if (!isEnable) {
            RCRTCAudioMixer.getInstance().stop();
            isSubscribeAudio(!isEnable);
            setAudioScenrio(isEnable, true);
            return;
        }
        if (TextUtils.isEmpty(url)) {
            return;
        }
        try {

            String filePath = FileUtils.getCacheDir(getActivity(), FileUtils.examDownloadDirectory);
            String fileName = url.substring(url.lastIndexOf("/") + 1);
            if (FileUtils.isFileExist(filePath + File.separator + fileName)) {
                isSubscribeAudio(!isEnable);
                if (isEnable) {
                    RCRTCAudioMixer.getInstance().startMix(filePath + File.separator + fileName, RCRTCAudioMixer.Mode.NONE, true, -1);
                    RCRTCAudioMixer.getInstance().setVolume(100);
                    RCRTCAudioMixer.getInstance().seekTo(0);
                }
                setAudioScenrio(isEnable, true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void playMetronome(PlayMidi playMidi, boolean deviceSync) {
        isPlaySound = playMidi.isEnable();
        try {
            PlayMidiNumber = 0;
            if (playMteronomeRunnable != null) {
                handler.removeCallbacks(playMteronomeRunnable);
                handler = null;
                playMteronomeRunnable = null;
                soundPool.stop(tickVoiceId);
                soundPool.stop(tockVoiceId);
                if (!playMidi.isEnable()) {
                    isSubscribeAudio(!playMidi.isEnable());
                    setAudioScenrio(playMidi.isEnable(), deviceSync);
                }
                //                adapter.notifyPositon(0);
                //                new Handler().postDelayed(() -> adapter.notifyPositon(0),100);
            }
            if (playMidi.isEnable()) {

                if (playMidi.getCustomType() == 0) {
                    tvTick.setText("1/4");
                }
                if (playMidi.getCustomType() == 1) {
                    tvTick.setText("2/4");
                }
                if (playMidi.getCustomType() == 2) {
                    tvTick.setText("3/4");
                }
                if (playMidi.getCustomType() == 3) {
                    tvTick.setText("4/4");
                }
                if (playMidi.getCustomType() == 4) {
                    tvTick.setText("6/8");
                }
                tvTock.setText(playMidi.getRate() + "");
                AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                double maxVolume = Double.valueOf(am.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
                if (maxVolume <= 0) {
                    maxVolume = 10;
                }
                LogUtils.e(playMidi.getPlayVolume() + ":" + Math.floor(playMidi.getPlayVolume() / (100 / maxVolume)));
                am.setStreamVolume(AudioManager.STREAM_MUSIC, (int) Math.floor(playMidi.getPlayVolume() / (100 / maxVolume)), AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                //                am.setStreamVolume(AudioManager.STREAM_MUSIC, (int) Math.floor(playMidi.getPlayVolume()/(100/maxVolume)),AudioManager.FLAG_SHOW_UI );
                isSubscribeAudio(!playMidi.isEnable());
                double delayMillis = 1 / (playMidi.getRate() / 60d) * 1000;
                recyclerView.setNumColumns(playMidi.getCustomType() == 4 ? 6 : playMidi.getCustomType() + 1);
                adapter.setData(playMidi.getCustomType() == 4 ? 6 : playMidi.getCustomType() + 1, delayMillis);
                handler = new Handler();
                playMteronomeRunnable = new Runnable() {
                    @Override
                    public void run() {
                        boolean tickOrTock;
                        if (playMidi.getCustomType() == 0 && PlayMidiNumber % 1 == 0) {
                            tickOrTock = true;
                        } else if (playMidi.getCustomType() == 1 && PlayMidiNumber % 2 == 0) {
                            tickOrTock = true;
                        } else if (playMidi.getCustomType() == 2 && PlayMidiNumber % 3 == 0) {
                            tickOrTock = true;
                        } else if (playMidi.getCustomType() == 3 && PlayMidiNumber % 4 == 0) {
                            tickOrTock = true;
                        } else if (playMidi.getCustomType() == 4 && PlayMidiNumber % 6 == 0) {
                            tickOrTock = true;
                        } else {
                            tickOrTock = false;
                        }
                        adapter.notifyPositon(PlayMidiNumber % (playMidi.getCustomType() == 4 ? 6 : playMidi.getCustomType() + 1));
                        if (tickOrTock) {
                            soundPool.play(tickVoiceId, 1F, 1F, 0, 0, 1F);
                        } else {
                            soundPool.play(tockVoiceId, 1F, 1F, 0, 0, 1F);
                        }
                        PlayMidiNumber++;
                        handler.postDelayed(this, (long) delayMillis);
                    }
                };
                handler.postDelayed(playMteronomeRunnable, 0);
                setAudioScenrio(playMidi.isEnable(), deviceSync);
            }

        } catch (Exception e) {
        }
    }

    private void mteronomeSoundPool() {

        SoundPool.Builder builder = new SoundPool.Builder();
        //传入最多播放音频数量,
        builder.setMaxStreams(2);
        //AudioAttributes是一个封装音频各种属性的方法
        AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
        //设置音频流的合适的属性
        attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
        //加载一个AudioAttributes
        builder.setAudioAttributes(attrBuilder.build());

        soundPool = builder.build();

        tickVoiceId = soundPool.load(getContext(), R.raw.tick, 0);
        tockVoiceId = soundPool.load(getContext(), R.raw.tock, 0);

    }

    private void isSubscribeAudio(boolean isSubscribe) {
        UserInfo userInfo = classViewModel.getUserInfo().getValue();
        List<ClassMember> memberlist = classViewModel.getMemberList().getValue();
        if (null != userInfo && null != memberlist && memberlist.size() > 0) {
            for (int i = 0; i < memberlist.size(); i++) {
                if (memberlist.get(i).getRole() != Role.LECTURER && !memberlist.get(i).getUserId().equals(userInfo.getUserId())) {
                    classViewModel.enableRTCAVInputStream(memberlist.get(i).getUserId(), isSubscribe);
                }
            }
        }
    }

    private boolean audioScenario;

    private void setAudioScenrio(boolean isChecked, boolean deviceSync) {
        if (!isChecked && (isPlayMusic || isPlaySound)) {
            return;
        }
        if (isChecked && audioScenario == isChecked) {
            return;
        }
        audioScenario = isChecked;

        try {
            RCRTCEngine.getInstance().getDefaultAudioStream().changeAudioScenario(isChecked ? RCRTCParamsType.AudioScenario.MUSIC_CLASSROOM : RCRTCParamsType.AudioScenario.DEFAULT, () -> {
                int nsLevel = RtcManager.getInstance().getNsLevel();
                if (nsLevel == 0) {
                    if (isChecked) {
                        RCRTCEngine.getInstance().getDefaultAudioStream().setAudioConfig(RCRTCAudioStreamConfig.Builder.create().setNoiseSuppressionLevel(RCRTCParamsType.NSLevel.NS_VERYHIGH)
                                .setEchoCancel(RCRTCParamsType.AECMode.AEC_MODE2)
                                .enableAGCControl(false)
                                .setNoiseSuppression(RCRTCParamsType.NSMode.NS_MODE0)
                                .enableHighPassFilter(false).build());
                    } else {
                        RCRTCEngine.getInstance().getDefaultAudioStream().setAudioConfig(RCRTCAudioStreamConfig.Builder.create().setNoiseSuppressionLevel(RCRTCParamsType.NSLevel.NS_VERYHIGH).build());
                    }

                }
                RCRTCEngine.getInstance().init(getContext(), RCRTCConfig.Builder.create().enableStereo(true).build());
            });

        } catch (Exception e) {
            e.printStackTrace();
            RongIM.connect(UserRepository.imToken, new RongIMClient.ConnectCallback() {
                @Override
                public void onSuccess(String s) {
                    RCRTCEngine.getInstance().getDefaultAudioStream().changeAudioScenario(isChecked ? RCRTCParamsType.AudioScenario.MUSIC_CLASSROOM : RCRTCParamsType.AudioScenario.DEFAULT, () -> {
                        int nsLevel = RtcManager.getInstance().getNsLevel();
                        if (nsLevel == 0) {
                            if (isChecked) {
                                RCRTCEngine.getInstance().getDefaultAudioStream().setAudioConfig(RCRTCAudioStreamConfig.Builder.create().setNoiseSuppressionLevel(RCRTCParamsType.NSLevel.NS_VERYHIGH)
                                        .setEchoCancel(RCRTCParamsType.AECMode.AEC_MODE2)
                                        .enableAGCControl(false)
                                        .setNoiseSuppression(RCRTCParamsType.NSMode.NS_MODE0)
                                        .enableHighPassFilter(false).build());
                            } else {
                                RCRTCEngine.getInstance().getDefaultAudioStream().setAudioConfig(RCRTCAudioStreamConfig.Builder.create().setNoiseSuppressionLevel(RCRTCParamsType.NSLevel.NS_VERYHIGH).build());
                            }

                        }
                        RCRTCEngine.getInstance().init(getContext(), RCRTCConfig.Builder.create().enableStereo(true).build());
                    });
                }

                @Override
                public void onError(RongIMClient.ConnectionErrorCode connectionErrorCode) {

                }

                @Override
                public void onDatabaseOpened(RongIMClient.DatabaseOpenStatus databaseOpenStatus) {

                }
            });
        }
        if (deviceSync && classViewModel != null) {
            classViewModel.deviceSyncMusicMode(roomId, isChecked);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            soundPool.release();
            soundPool = null;
            handler.removeCallbacks(playMteronomeRunnable);
            handler = null;
        } catch (Exception e) {

        }

    }

}
