/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.micode.notes.tool;

import android.content.Context;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.util.Log;
import android.widget.Toast;

import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AudioTool {
    private static final String TAG = "AudioTool";

    // 音频引用标签格式 [音频:filename.mp3]
    private static final String AUDIO_PATTERN = "\\[音频:([^\\]]+)\\]";
    private static final Pattern sAudioPattern = Pattern.compile(AUDIO_PATTERN);

    private static MediaRecorder mRecorder = null;
    private static MediaPlayer mPlayer = null;
    private static String mCurrentRecordFile = null;
    private static boolean mIsRecording = false;
    private static boolean mIsPlaying = false;

    /**
     * 获取音频存储目录
     */
    public static File getNotesAudioDir(Context context) {
        File dir = new File(context.getFilesDir(), "audios");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        return dir;
    }

    /**
     * 开始录音
     * @param context 上下文
     * @return 临时录音文件路径
     */
    public static String startRecording(Context context) {
        if (mIsRecording) {
            return null;
        }

        try {
            // 创建临时录音文件
            String fileName = "temp_record_" + UUID.randomUUID().toString() + ".mp3";
            File audioFile = new File(getNotesAudioDir(context), fileName);
            
            mRecorder = new MediaRecorder();
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            mRecorder.setOutputFile(audioFile.getAbsolutePath());
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            
            mRecorder.prepare();
            mRecorder.start();
            mIsRecording = true;
            mCurrentRecordFile = audioFile.getAbsolutePath();
            
            return mCurrentRecordFile;
        } catch (IOException e) {
            Log.e(TAG, "Failed to start recording", e);
            stopRecording();
            return null;
        }
    }

    /**
     * 停止录音
     * @return 录音文件路径，如果失败则返回null
     */
    public static String stopRecording() {
        if (!mIsRecording || mRecorder == null) {
            return null;
        }
        
        try {
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;
            mIsRecording = false;
            return mCurrentRecordFile;
        } catch (Exception e) {
            Log.e(TAG, "Failed to stop recording", e);
            return null;
        } finally {
            mIsRecording = false;
            mRecorder = null;
        }
    }

    /**
     * 播放音频文件
     * @param context 上下文
     * @param fileName 音频文件名
     * @return 是否成功开始播放
     */
    public static boolean playAudio(Context context, String fileName) {
        if (mIsPlaying || TextUtils.isEmpty(fileName)) {
            return false;
        }
        
        try {
            File audioFile = new File(getNotesAudioDir(context), fileName);
            if (!audioFile.exists()) {
                return false;
            }
            
            mPlayer = new MediaPlayer();
            mPlayer.setDataSource(audioFile.getAbsolutePath());
            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    stopPlaying();
                }
            });
            
            mPlayer.prepare();
            mPlayer.start();
            mIsPlaying = true;
            
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Failed to play audio", e);
            stopPlaying();
            return false;
        }
    }

    /**
     * 停止播放
     */
    public static void stopPlaying() {
        if (mPlayer != null) {
            try {
                mPlayer.stop();
                mPlayer.release();
            } catch (Exception e) {
                Log.e(TAG, "Failed to stop playing", e);
            } finally {
                mPlayer = null;
                mIsPlaying = false;
            }
        }
    }

    /**
     * 将音频文件复制到应用私有目录
     * @param context 上下文
     * @param sourceUri 源音频文件Uri
     * @return 保存后的文件名，失败则返回null
     */
    public static String copyAudioToPrivateStorage(Context context, Uri sourceUri) {
        if (sourceUri == null) {
            return null;
        }

        FileChannel sourceChannel = null;
        FileChannel destChannel = null;
        
        try {
            // 生成唯一文件名
            String filename = UUID.randomUUID().toString() + ".mp3";
            File destFile = new File(getNotesAudioDir(context), filename);
            
            // 获取输入流
            FileInputStream inputStream = (FileInputStream) context.getContentResolver().openInputStream(sourceUri);
            if (inputStream == null) {
                return null;
            }
            
            // 创建输出流
            FileOutputStream outputStream = new FileOutputStream(destFile);
            
            // 复制文件
            sourceChannel = inputStream.getChannel();
            destChannel = outputStream.getChannel();
            destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
            
            return filename;
        } catch (Exception e) {
            Log.e(TAG, "Error copying audio file to private storage", e);
            return null;
        } finally {
            try {
                if (sourceChannel != null) {
                    sourceChannel.close();
                }
                if (destChannel != null) {
                    destChannel.close();
                }
            } catch (IOException e) {
                // 忽略关闭错误
            }
        }
    }

    /**
     * 处理笔记文本中的音频标记，将其替换为ImageSpan
     * @param context 上下文
     * @param content 笔记内容
     * @return 处理后的富文本内容
     */
    public static Spannable processAudioMarkers(Context context, CharSequence content) {
        if (content == null || content.length() == 0) {
            return new SpannableString("");
        }

        // 如果输入已经是Spannable，直接使用它，否则创建新的SpannableString
        Spannable spannable;
        if (content instanceof Spannable) {
            spannable = (Spannable) content;
        } else {
            spannable = new SpannableString(content);
        }

        // 使用String进行正则匹配
        String contentString = content.toString();
        Matcher matcher = sAudioPattern.matcher(contentString);
        
        while (matcher.find()) {
            String audioName = matcher.group(1);
            if (!TextUtils.isEmpty(audioName)) {
                // 创建音频图标Span
                ImageSpan audioSpan = new ImageSpan(context, R.drawable.ic_audio_file);
                spannable.setSpan(audioSpan, matcher.start(), matcher.end(), 
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        
        return spannable;
    }

    /**
     * 从文本中提取所有音频文件名
     * @param content 笔记内容
     * @return 音频文件名数组
     */
    public static String[] extractAudiosFromText(String content) {
        if (TextUtils.isEmpty(content)) {
            return new String[0];
        }
        
        Matcher matcher = sAudioPattern.matcher(content);
        java.util.ArrayList<String> audios = new java.util.ArrayList<>();
        
        while (matcher.find()) {
            String audioName = matcher.group(1);
            if (!TextUtils.isEmpty(audioName)) {
                audios.add(audioName);
            }
        }
        
        return audios.toArray(new String[0]);
    }

    /**
     * 检查是否正在录音
     */
    public static boolean isRecording() {
        return mIsRecording;
    }

    /**
     * 检查是否正在播放
     */
    public static boolean isPlaying() {
        return mIsPlaying;
    }

    /**
     * 获取与笔记关联的音频文件
     * @param context 上下文
     * @param noteId 笔记ID
     * @return 音频文件对象，如果不存在则返回null
     */
    public static File getAudioFile(Context context, long noteId) {
        try {
            // 当删除笔记时，需要找到与该笔记关联的所有音频文件并删除
            Cursor cursor = context.getContentResolver().query(
                    Notes.CONTENT_DATA_URI,
                    new String[] { DataColumns.CONTENT },
                    DataColumns.NOTE_ID + "=? AND " + DataColumns.MIME_TYPE + "=?",
                    new String[] { String.valueOf(noteId), "vnd.android.cursor.item/text_note" },
                    null);
                    
            if (cursor != null && cursor.moveToFirst()) {
                String content = cursor.getString(0);
                cursor.close();
                
                if (!TextUtils.isEmpty(content)) {
                    // 从内容中提取音频文件名
                    String[] audioFiles = extractAudiosFromText(content);
                    if (audioFiles.length > 0) {
                        // 返回第一个找到的音频文件
                        File audioFile = new File(getNotesAudioDir(context), audioFiles[0]);
                        if (audioFile.exists()) {
                            return audioFile;
                        }
                    }
                }
            }
            return null;
        } catch (Exception e) {
            Log.e(TAG, "Error getting audio file for note: " + noteId, e);
            return null;
        }
    }
} 