package cc.winboll.studio.midiplayer;

/**
 * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
 * @Date 2025/06/29 10:10
 * @Describe Midi 播放窗口
 */
import android.app.Activity;
import android.content.Context;
import android.media.midi.MidiInputPort;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import cc.winboll.studio.libappbase.LogUtils;
import com.hjq.toast.ToastUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MidiPlayerActivity extends WinBoLLActivity {

    public static final String TAG = "MidiPlayerActivity";

    private MidiPlayer mMidiPlayer;
    private Button mPlayBtn, mPauseBtn, mStopBtn, mTestBtn;
    private ListView mTrackListView;
    private ListView mFileListView;
    private TrackAdapter mTrackAdapter;
    private TextView mFileNameTv;
    private List<File> mMidiFileList = new ArrayList<>();

    @Override
    public Activity getActivity() {
        return this;
    }

    @Override
    public String getTag() {
        return TAG;
    }

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

        // 初始化控件
        mPlayBtn = (Button) findViewById(R.id.btn_play);
        mPauseBtn = (Button) findViewById(R.id.btn_pause);
        mStopBtn = (Button) findViewById(R.id.btn_stop);
        mTestBtn = (Button) findViewById(R.id.btn_test);
        mTrackListView = (ListView) findViewById(R.id.lv_tracks);
        mFileListView = (ListView) findViewById(R.id.lv_midi_files);
        mFileNameTv = (TextView) findViewById(R.id.tv_file_name);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            initMidiPlayer();
            loadMidiFileList();
            initControlButtons();
            initTestButton();
        } else {
            mFileNameTv.setText("当前设备不支持MIDI播放（需Android 6.0及以上）");
            disableButtons();
        }

        copyAssetsMidiFiles();
    }

    // 初始化测试按钮及1分钟测试逻辑
    private void initTestButton() {
        mTestBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					testMidiOutput();
				}
			});
    }

    /**
     * 1分钟MIDI测试序列：包含多样音符组合，验证输出功能
     */
    private void testMidiOutput() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            ToastUtils.show("测试需要Android 6.0及以上");
            return;
        }

        if (mMidiPlayer == null) {
            initMidiPlayer();
        }

        new Thread(new Runnable() {
				@Override
				public void run() {
					// 确保合成器连接
					if (!mMidiPlayer.isSynthConnected()) {
						LogUtils.d(TAG, "测试：连接合成器中...");
						mMidiPlayer.connectToSynth();

						// 最多等待3秒连接
						int waitCount = 0;
						while (!mMidiPlayer.isSynthConnected() && waitCount < 30) {
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
								Thread.currentThread().interrupt();
								return;
							}
							waitCount++;
						}
					}

					final MidiInputPort inputPort = mMidiPlayer.getInputPort();
					if (inputPort == null) {
						LogUtils.d(TAG, "测试失败：无可用输入端口");
						runOnUiThread(new Runnable() {
								@Override
								public void run() {
									ToastUtils.show("测试失败：未找到输入端口");
								}
							});
						return;
					}

					try {
						runOnUiThread(new Runnable() {
								@Override
								public void run() {
									ToastUtils.show("开始1分钟测试音符...");
								}
							});

						// 测试序列定义：[音高, 力度, 时长(毫秒)]
						int[][] noteSequence = {
							// 0-10秒：低音区短音符
							{48, 64, 200}, {50, 64, 200}, {52, 64, 200}, {53, 64, 200},
							{55, 64, 200}, {57, 64, 200}, {59, 64, 200}, {60, 64, 400},

							// 10-20秒：中音区连音
							{60, 72, 300}, {62, 72, 300}, {64, 72, 300}, {65, 72, 300},
							{67, 72, 300}, {69, 72, 300}, {71, 72, 300}, {72, 72, 600},

							// 20-30秒：高音区跳音
							{72, 80, 150}, {76, 80, 150}, {79, 80, 150}, {84, 80, 300},
							{79, 80, 150}, {76, 80, 150}, {72, 80, 150}, {69, 80, 450},

							// 30-40秒：和弦组合
							{60, 64, 400}, {64, 64, 400}, {67, 64, 400}, // C和弦
							{62, 64, 400}, {65, 64, 400}, {69, 64, 400}, // Dm和弦
							{64, 64, 400}, {67, 64, 400}, {71, 64, 400}, // Em和弦

							// 40-50秒：渐强长音
							{55, 40, 1000}, {55, 60, 1000}, {55, 80, 1000}, {55, 100, 1000},

							// 50-60秒：快速音阶
							{50, 70, 100}, {52, 70, 100}, {53, 70, 100}, {55, 70, 100},
							{57, 70, 100}, {59, 70, 100}, {60, 70, 100}, {62, 70, 100},
							{64, 70, 100}, {65, 70, 100}, {67, 70, 100}, {69, 70, 100},
							{71, 70, 100}, {72, 90, 500}
						};

						// 发送测试序列
						for (int[] note : noteSequence) {
							if (!mMidiPlayer.isSynthConnected()) {
								LogUtils.d(TAG, "连接已断开，停止测试");
								break;
							}

							int pitch = note[0];
							int velocity = note[1];
							int duration = note[2];

							// 发送音符开启事件
							byte[] noteOn = new byte[]{(byte) 0x90, (byte) pitch, (byte) velocity};
							inputPort.send(noteOn, 0, noteOn.length);
							//LogUtils.d(TAG, "测试音符：音高=" + pitch + ", 力度=" + velocity + ", 时长=" + duration + "ms");

							// 等待音符时长
							Thread.sleep(duration);

							// 发送音符关闭事件
							byte[] noteOff = new byte[]{(byte) 0x80, (byte) pitch, 0};
							inputPort.send(noteOff, 0, noteOff.length);
						}

						runOnUiThread(new Runnable() {
								@Override
								public void run() {
									ToastUtils.show("1分钟测试完成");
								}
							});

					} catch (final Exception e) {
						LogUtils.d(TAG, "测试出错：" + e.getMessage());
						runOnUiThread(new Runnable() {
								@Override
								public void run() {
									ToastUtils.show("测试出错：" + e.getMessage());
								}
							});
					}
				}
			}).start();
    }

    // 拷贝Assets中的MIDI文件到本地
    private void copyAssetsMidiFiles() {
        final AssetMidiCopier copier = new AssetMidiCopier(this);
        new Thread(new Runnable() {
				@Override
				public void run() {
					final boolean success = copier.copyMidiFiles();
					runOnUiThread(new Runnable() {
							@Override
							public void run() {
								if (success) {
									File midiDir = copier.getMidiTargetDir();
									LogUtils.d(TAG, "MIDI文件拷贝成功，路径：" + midiDir.getAbsolutePath());
									// 重新加载文件列表
									loadMidiFileList();
								} else {
									ToastUtils.show("MIDI文件拷贝失败");
								}
							}
						});
				}
			}).start();
    }

    // 初始化MIDI播放器
    private void initMidiPlayer() {
        mMidiPlayer = new MidiPlayer(this);
        mMidiPlayer.setOnSynthConnectedListener(new MidiPlayer.OnSynthConnectedListener() {
				@Override
				public void onConnected(final boolean success) {
					runOnUiThread(new Runnable() {
							@Override
							public void run() {
								if (success) {
									ToastUtils.show("MIDI合成器连接成功");
								} else {
									ToastUtils.show("未找到MIDI合成器，请安装第三方合成器应用");
								}
							}
						});
				}
			});
    }

    // 加载本地MIDI文件列表
    private void loadMidiFileList() {
        File midiDir = new File(getFilesDir(), "midi");
        if (!midiDir.exists()) {
            midiDir.mkdirs();
            mFileNameTv.setText("midi目录已创建，等待文件拷贝...");
            return;
        }

        mMidiFileList.clear();
        File[] files = midiDir.listFiles();
        if (files != null) {
            for (File file : files) {
                String name = file.getName().toLowerCase();
                if (name.endsWith(".mid") || name.endsWith(".midi")) {
                    mMidiFileList.add(file);
                }
            }
        }

        if (mMidiFileList.isEmpty()) {
            mFileNameTv.setText("midi目录中无可用文件");
        } else {
            showFileList();
            mFileNameTv.setText("找到" + mMidiFileList.size() + "个MIDI文件");
        }
    }

    // 显示MIDI文件列表
    private void showFileList() {
        List<String> fileNameList = new ArrayList<>();
        for (File file : mMidiFileList) {
            fileNameList.add(file.getName());
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
			this,
			android.R.layout.simple_list_item_1,
			fileNameList
        );
        mFileListView.setAdapter(adapter);

        mFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
				@Override
				public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
					mMidiPlayer.stop();
					File selectedFile = mMidiFileList.get(position);
					boolean loaded = mMidiPlayer.loadMidiFile(selectedFile);
					if (loaded) {
						mFileNameTv.setText("当前文件：" + selectedFile.getName());
						initTrackList();
						ToastUtils.show("已加载：" + selectedFile.getName());
					} else {
						mFileNameTv.setText("文件加载失败：" + selectedFile.getName());
					}
				}
			});
    }

    // 初始化轨道列表
    private void initTrackList() {
        mTrackAdapter = new TrackAdapter(this, mMidiPlayer);
        mTrackListView.setAdapter(mTrackAdapter);
    }

    // 初始化播放控制按钮
    private void initControlButtons() {
        mPlayBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					if (mMidiPlayer != null) {
						mMidiPlayer.start();
					}
				}
			});

        mPauseBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					if (mMidiPlayer != null) {
						mMidiPlayer.pause();
					}
				}
			});

        mStopBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					if (mMidiPlayer != null) {
						mMidiPlayer.stop();
					}
				}
			});
    }

    // 禁用所有按钮（低版本设备）
    private void disableButtons() {
        mPlayBtn.setEnabled(false);
        mPauseBtn.setEnabled(false);
        mStopBtn.setEnabled(false);
        mTestBtn.setEnabled(false);
    }

    // 轨道列表适配器
    private class TrackAdapter extends android.widget.BaseAdapter {
        private Context mContext;
        private MidiPlayer mPlayer;

        public TrackAdapter(Context context, MidiPlayer player) {
            mContext = context;
            mPlayer = player;
        }

        @Override
        public int getCount() {
            return mPlayer != null ? mPlayer.getTrackCount() : 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = getLayoutInflater().inflate(R.layout.item_track, parent, false);
            TextView trackNameTv = (TextView) view.findViewById(R.id.tv_track_name);
            final Button muteBtn = (Button) view.findViewById(R.id.btn_mute);
            SeekBar volumeSb = (SeekBar) view.findViewById(R.id.sb_volume);

            trackNameTv.setText("轨道 " + (position + 1));
            muteBtn.setText("静音");

            // 静音按钮逻辑
            muteBtn.setOnClickListener(new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						boolean isMuted = muteBtn.isSelected();
						mPlayer.setTrackMute(position, !isMuted);
						muteBtn.setSelected(!isMuted);
						muteBtn.setText(isMuted ? "静音" : "已静音");
					}
				});

            // 音量条（预留逻辑）
            volumeSb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
					@Override
					public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
						// 可添加音量控制逻辑（如发送MIDI音量事件）
					}

					@Override
					public void onStartTrackingTouch(SeekBar seekBar) {}

					@Override
					public void onStopTrackingTouch(SeekBar seekBar) {}
				});

            return view;
        }
    }

    // 日志查看按钮点击事件
    public void onLog(View view) {
        App.getWinBoLLActivityManager().startLogActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMidiPlayer != null) {
            mMidiPlayer.stop();
        }
    }
}

