/*
 * 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.ui;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.util.DisplayMetrics;
import android.widget.HorizontalScrollView;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import android.util.Base64;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.graphics.Typeface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.content.ContentResolver;
import android.content.res.Resources;
// import android.support.annotation.NonNull;
import android.Manifest;
import android.graphics.Color;
import android.os.Environment;
import android.text.format.DateUtils;
import android.view.ViewGroup;
import android.content.ActivityNotFoundException;

import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.wasabeef.richeditor.RichEditor;

import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.ChecklistManager;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;


/**
 * 笔记编辑活动
 * 负责处理笔记的创建、编辑和预览功能
 * 实现了笔记设置变化监听器和文本视图变化监听器接口
 */
public class NoteEditActivity extends Activity implements OnClickListener,
        NoteSettingChangedListener, OnTextViewChangeListener {
    /**
     * 头部视图持有者类
     * 用于缓存头部视图的控件引用，提高性能
     */
    private class HeadViewHolder {
        public TextView tvModified;       // 最后修改时间文本视图
        public ImageView ivAlertIcon;     // 提醒图标
        public TextView tvAlertDate;      // 提醒日期文本视图
        public ImageView ibSetBgColor;    // 设置背景颜色按钮
    }

    /**
     * 背景选择器按钮映射
     * 用于将背景选择按钮ID映射到对应的背景颜色常量
     */
    private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
    static {
        sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
        sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
        sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
        sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
        sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
    }

    /**
     * 背景选择器选中状态映射
     * 用于将背景颜色常量映射到对应的选中状态图标ID
     */
    private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
    static {
        sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
        sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
        sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
        sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
        sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
    }

    /**
     * 字体大小按钮映射
     * 用于将字体大小选择按钮ID映射到对应的字体大小常量
     */
    private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
    static {
        sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
        sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
        sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
        sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
    }

    /**
     * 字体选择器选中状态映射
     * 用于将字体大小常量映射到对应的选中状态图标ID
     */
    private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
    static {
        sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
        sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
        sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
        sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
    }

    private static final String TAG = "NoteEditActivity";  // 日志标签
    private static final int REQUEST_CODE_PICK_IMAGE = 100;  // 图片选择请求码 OMO
    private static final int PHOTO_REQUEST = 100;  // 请求照片

    private HeadViewHolder mNoteHeaderHolder;        // 头部视图持有者
    private View mHeadViewPanel;                    // 头部视图面板
    private View mNoteBgColorSelector;              // 背景颜色选择器
    private View mFontSizeSelector;                 // 字体大小选择器
    private RichEditor mNoteEditor;                  // 富文本编辑器
    private View mNoteEditorPanel;                  // 笔记编辑器面板
    private HorizontalScrollView mFloatingToolbar;  // 浮动富文本工具栏
    private WorkingNote mWorkingNote;               // 工作笔记对象
    private SharedPreferences mSharedPrefs;         // 共享偏好设置
    private int mFontSizeId;                        // 字体大小ID
    private ImageButton mBtnInsertImage;            // 插入图片按钮 OMO
    private String mText;                           // 用于存储富文本内容
    private int mNoteLength;                        // 文本长度

    private static final String PREFERENCE_FONT_SIZE = "pref_font_size";  // 字体大小偏好设置键
    private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;  // 快捷图标标题最大长度

    public static final String TAG_CHECKED = String.valueOf('\u221A');  // 已勾选标记
    public static final String TAG_UNCHECKED = String.valueOf('\u25A1');  // 未勾选标记

    private LinearLayout mEditTextList;             // 编辑文本列表（用于清单模式）
    private String mUserQuery;                      // 用户查询字符串
    private Pattern mPattern;                       // 正则表达式模式（用于高亮查询结果）
    private ChecklistManager mChecklistManager;     // 清单管理器（OMO）
    
    // 标签管理相关控件
    private LinearLayout mTagManagementSection;     // 标签管理区域
    private LinearLayout mExistingTagsContainer;     // 现有标签容器
    private LinearLayout mBottomTagsContainer;      // 底部标签显示容器
    private EditText mTagInput;                     // 标签输入框
    private Button mAddTagButton;                   // 添加标签按钮
    private ArrayList<String> mTagsList;            // 标签列表
    
    // 搜索历史相关
    private static final String PREFERENCE_SEARCH_HISTORY = "search_history";  // 搜索历史偏好设置键
    private static final int MAX_SEARCH_HISTORY = 20;  // 最大搜索历史记录数

    /**
     * 创建活动时调用
     * @param savedInstanceState 保存的实例状态
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.note_edit);  // 设置布局

        initResources();  // 先初始化资源，再初始化活动状态（OMO）

        // 初始化清单管理器
        mChecklistManager = new ChecklistManager(getContentResolver());

        // 如果没有保存的状态且无法初始化活动状态，则结束活动
        if (savedInstanceState == null && !initActivityState(getIntent())) {
            finish();
            return;
        }
    }

    /**
     * 当前活动在内存不足时可能被杀死。一旦被杀死，当用户再次加载此活动时，我们应该恢复以前的状态
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
            if (!initActivityState(intent)) {
                finish();
                return;
            }
            Log.d(TAG, "Restoring from killed activity");
        }
    }

    /**
     * 初始化活动状态
     * 根据传入的意图设置工作笔记的状态
     * @param intent 传入的意图
     * @return 是否初始化成功
     */
    private boolean initActivityState(Intent intent) {
        /**
         * If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
         * then jump to the NotesListActivity
         */
        mWorkingNote = null;
        if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
            long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
            mUserQuery = "";

            /**
             * Starting from the searched result
             */
            if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
                noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
                mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
            }

            if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE) && !DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_CHECKLIST)) {
                Intent jump = new Intent(this, NotesListActivity.class);
                startActivity(jump);
                showToast(R.string.error_note_not_exist);
                finish();
                return false;
            } else {
                mWorkingNote = WorkingNote.load(this, noteId);
                if (mWorkingNote == null) {
                    Log.e(TAG, "load note failed with note id" + noteId);
                    finish();
                    return false;
                }
            }
            
            // 保存搜索历史
            if (!TextUtils.isEmpty(mUserQuery)) {
                saveSearchHistory(mUserQuery);
            }
            getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
                            | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
            // New note
            long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
            int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            int widgetType = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_TYPE,
                    Notes.TYPE_WIDGET_INVALIDE);
            int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
                    ResourceParser.getDefaultBgId(this));

            // Parse call-record note
            String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
            if (callDate != 0 && phoneNumber != null) {
                if (TextUtils.isEmpty(phoneNumber)) {
                    Log.w(TAG, "The call record number is null");
                }
                long noteId = 0;
                if ((noteId = DataUtils.getNoteIdByPhoneNumberAndCallDate(getContentResolver(),
                        phoneNumber, callDate)) > 0) {
                    mWorkingNote = WorkingNote.load(this, noteId);
                    if (mWorkingNote == null) {
                        Log.e(TAG, "load call note failed with note id" + noteId);
                        finish();
                        return false;
                    }
                } else {
                    mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId,
                            widgetType, bgResId);
                    mWorkingNote.convertToCallNote(phoneNumber, callDate);
                }
            } else {
                mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, bgResId);

                // 设置笔记类型
                int noteType = intent.getIntExtra(Notes.INTENT_EXTRA_NOTE_TYPE, Notes.TYPE_NOTE);

                // 使用ChecklistManager处理清单模式标记（OMO）
                if (mChecklistManager != null) {
                    mChecklistManager.handleChecklistModeFromIntent(intent, mWorkingNote);
                }
            }

            // 处理加密便签
            boolean isEncrypted = intent.getBooleanExtra("is_encrypted", false);
            if (isEncrypted) {
                String password = intent.getStringExtra("password");
                if (password != null && !password.isEmpty()) {
                    mWorkingNote.setEncrypted(true);
                    // 保存密码（需要在便签保存后）
                    mWorkingNote.setPassword(password);
                }
            }

            getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
                            | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        } else {
            Log.e(TAG, "Intent not specified action, should not support");
            finish();
            return false;
        }
        mWorkingNote.setOnSettingStatusChangedListener(this);
        return true;
    }

    /**
     * 活动恢复时调用
     */
    @Override
    protected void onResume() {
        super.onResume();
        initNoteScreen();  // 初始化笔记屏幕
    }

    /**
     * 初始化笔记屏幕
     * 设置笔记编辑器的文本外观、内容和选择模式
     */
    private void initNoteScreen() {
        // 检查必要的视图是否已初始化
        if (mHeadViewPanel == null || mNoteEditorPanel == null || mNoteEditor == null) {
            Log.e(TAG, "Some views are not initialized! Check initResources method.");
            return;
        }

        // 设置富文本编辑器字体大小
        setRichEditorFontSize(mFontSizeId);

        // 根据笔记模式设置显示方式
        if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
            switchToListMode(mWorkingNote.getContent());  // 切换到清单模式
            mNoteEditor.setVisibility(View.GONE);
            mEditTextList.setVisibility(View.VISIBLE);
        } else {
            // 切换到富文本模式
            mEditTextList.setVisibility(View.GONE);
            mNoteEditor.setVisibility(View.VISIBLE);

            // 获取笔记原始内容（为空则赋空字符串，避免空指针）
            String content = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();

            // 无论内容是否为HTML格式，都检查并处理[IMAGE]标记
            String finalHtml = content;

            // 处理 [IMAGE] 标签，转换为 HTML img 标签
            Pattern imgPattern = Pattern.compile("\\[IMAGE\\]([^\\[]+)\\[/IMAGE\\]");
            Matcher imgMatcher = imgPattern.matcher(content);

            // 检查是否包含[IMAGE]标记
            if (imgMatcher.find()) {
                // 重新创建匹配器，因为第一次find会移动指针
                imgMatcher = imgPattern.matcher(content);
                StringBuffer htmlContent = new StringBuffer();

                // 遍历替换所有[IMAGE]标记为<img>标签
                while (imgMatcher.find()) {
                    String imgUri = imgMatcher.group(1); // 提取图片路径
                    Log.d(TAG, "Processing image URI: " + imgUri);

                    String imgHtmlUrl = "";
                    boolean isValidImage = false;

                    // 检查图片路径类型并生成有效的HTML图片URL
                    if (imgUri.startsWith("file://")) {
                        // 处理file://前缀的路径
                        String filePath = imgUri.substring(7);
                        File imgFile = new File(filePath);
                        if (imgFile.exists() && imgFile.isFile()) {
                            // 对于本地文件，转换为Base64编码以确保在WebView中显示
                            try {
                                InputStream is = new FileInputStream(imgFile);
                                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                byte[] buffer = new byte[4096];
                                int len;
                                while ((len = is.read(buffer)) > 0) {
                                    baos.write(buffer, 0, len);
                                }
                                String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
                                imgHtmlUrl = "data:image/jpeg;base64," + base64Data;
                                isValidImage = true;
                                is.close();
                                baos.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Error converting file to Base64: " + e.getMessage());
                            }
                        } else {
                            Log.e(TAG, "Image file not found: " + filePath);
                        }
                    } else if (imgUri.startsWith("/")) {
                        // 处理直接的绝对路径
                        File imgFile = new File(imgUri);
                        if (imgFile.exists() && imgFile.isFile()) {
                            // 对于本地文件，转换为Base64编码以确保在WebView中显示
                            try {
                                InputStream is = new FileInputStream(imgFile);
                                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                byte[] buffer = new byte[4096];
                                int len;
                                while ((len = is.read(buffer)) > 0) {
                                    baos.write(buffer, 0, len);
                                }
                                String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
                                imgHtmlUrl = "data:image/jpeg;base64," + base64Data;
                                isValidImage = true;
                                is.close();
                                baos.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Error converting file to Base64: " + e.getMessage());
                            }
                        } else {
                            Log.e(TAG, "Image file not found: " + imgUri);
                        }
                    } else {
                        // 其他URI格式，直接使用（包括Base64图片）
                        imgHtmlUrl = imgUri;
                        isValidImage = true;
                    }

                    if (isValidImage) {
                        // 生成HTML img标签
                        String imgHtmlTag = "<img src=\"" + imgHtmlUrl + "\" width=\"200\" height=\"200\"/><br/>";
                        imgMatcher.appendReplacement(htmlContent, imgHtmlTag);
                        Log.d(TAG, "Successfully replaced [IMAGE] tag with HTML img tag: " + imgHtmlTag);
                    } else {
                        // 如果图片无效，保留原标记，但添加错误提示
                        Log.w(TAG, "Invalid image, keeping original tag: " + imgMatcher.group(0));
                        imgMatcher.appendReplacement(htmlContent, imgMatcher.group(0));
                    }
                }
                imgMatcher.appendTail(htmlContent); // 拼接剩余文本
                finalHtml = htmlContent.toString();
                Log.d(TAG, "Final HTML content after processing [IMAGE] tags: " + finalHtml);
            } else {
                // 没有[IMAGE]标签，直接使用内容作为HTML（包括Base64图片）
                Log.d(TAG, "No [IMAGE] tags found, using content as HTML: " + content);
                finalHtml = content;
            }

            // 用RichEditor加载HTML内容
            mNoteEditor.setHtml(finalHtml);
            // 更新我们自己维护的HTML内容
            mCurrentHtmlContent = finalHtml;
        }

        // 隐藏所有背景选择的选中状态
        for (Integer id : sBgSelectorSelectionMap.keySet()) {
            findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
        }

        // 设置头部视图和编辑器面板的背景
        mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
        mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());

        // 设置最后修改时间
        mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
                mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
                        | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
                        | DateUtils.FORMAT_SHOW_YEAR));

        /**
         * TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
         * is not ready
         */
        showAlertHeader();  // 显示提醒头部
        
        // 加载现有标签
        loadExistingTags();
    }

    /**
     * 将包含[IMAGE]标签的文本转换为包含ImageSpan的SpannableString
     * @param text 包含[IMAGE]标签的文本
     * @return 包含ImageSpan的SpannableString
     */
    private SpannableString convertTextToSpannableWithImages(String text) {
        if (TextUtils.isEmpty(text)) {
            return new SpannableString("");
        }

        Log.d(TAG, "Converting text to Spannable with images: " + text);

        // 创建一个新的SpannableStringBuilder
        SpannableStringBuilder builder = new SpannableStringBuilder();

        // 查找所有[IMAGE]标签
        int startIndex = 0;
        int imageStart = text.indexOf("[IMAGE]", startIndex);

        while (imageStart != -1) {
            Log.d(TAG, "Found [IMAGE] tag at position: " + imageStart);

            // 添加[IMAGE]标签之前的文本
            builder.append(text.substring(startIndex, imageStart));

            // 查找当前[IMAGE]标签的结束位置
            int imageEnd = text.indexOf("[/IMAGE]", imageStart + "[IMAGE]".length());
            if (imageEnd == -1) {
                // 如果没有找到结束标签，添加剩余文本并退出循环
                builder.append(text.substring(imageStart));
                break;
            }

            Log.d(TAG, "Found [/IMAGE] tag at position: " + imageEnd);

            // 提取图片URI
            String imageUri = text.substring(imageStart + "[IMAGE]".length(), imageEnd);
            Log.d(TAG, "Extracted image URI: " + imageUri);

            // 保留原始的[IMAGE]uri[/IMAGE]标签，直接在上面添加ImageSpan
            String fullImageTag = "[IMAGE]" + imageUri + "[/IMAGE]";
            int tagStart = builder.length();
            builder.append(fullImageTag);

            // 尝试将图片路径转换为Drawable并创建ImageSpan
            try {
                Bitmap bitmap = null;

                // 检查图片路径类型：本地文件路径或URI
                if (imageUri.startsWith("file://")) {
                    // 处理file://前缀的路径
                    String filePath = imageUri.substring(7);
                    Log.d(TAG, "Loading image from file path (with file:// prefix): " + filePath);
                    bitmap = BitmapFactory.decodeFile(filePath);
                } else if (imageUri.startsWith("/")) {
                    // 处理直接的绝对路径
                    Log.d(TAG, "Loading image from absolute file path: " + imageUri);
                    bitmap = BitmapFactory.decodeFile(imageUri);
                } else {
                    // 处理其他URI格式
                    Log.d(TAG, "Loading image from URI: " + imageUri);
                    Uri uri = Uri.parse(imageUri);
                    if (uri != null) {
                        ContentResolver resolver = getContentResolver();
                        try (InputStream inputStream = resolver.openInputStream(uri)) {
                            if (inputStream != null) {
                                bitmap = BitmapFactory.decodeStream(inputStream);
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "Error loading image from URI: " + e.toString());
                        }
                    }
                }

                // 检查bitmap是否成功加载
                if (bitmap != null) {
                    Log.d(TAG, "Successfully decoded bitmap with dimensions: " + bitmap.getWidth() + "x" + bitmap.getHeight());

                    // 计算图片的合适大小，确保它能适应EditText的宽度
                    int screenWidth = getResources().getDisplayMetrics().widthPixels;
                    // 减去左右边距，确保图片能完整显示
                    int maxWidth = screenWidth - 40;
                    int imageWidth = bitmap.getWidth();
                    int imageHeight = bitmap.getHeight();

                    // 计算缩放比例
                    float scale = 1.0f;
                    if (imageWidth > maxWidth) {
                        scale = (float) maxWidth / (float) imageWidth;
                    }
                    Log.d(TAG, "Calculated scale: " + scale);

                    // 缩放图片（如果需要）
                    if (scale < 1.0f) {
                        bitmap = Bitmap.createScaledBitmap(bitmap, (int)(imageWidth * scale), (int)(imageHeight * scale), true);
                        Log.d(TAG, "Scaled bitmap to: " + bitmap.getWidth() + "x" + bitmap.getHeight());
                    }

                    // 创建Drawable并设置边界
                    Drawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), bitmap);
                    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

                    // 创建ImageSpan并添加到SpannableStringBuilder中
                    ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
                    builder.setSpan(imageSpan, tagStart, tagStart + fullImageTag.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);
                    Log.d(TAG, "Successfully added ImageSpan for: " + imageUri);
                } else {
                    Log.e(TAG, "Failed to decode bitmap from: " + imageUri);
                }
            } catch (Exception e) {
                Log.e(TAG, "Error loading image: " + e.toString());
            }

            // 更新索引，继续查找下一个[IMAGE]标签
            startIndex = imageEnd + "[/IMAGE]".length();
            imageStart = text.indexOf("[IMAGE]", startIndex);
        }

        // 添加剩余的文本
        builder.append(text.substring(startIndex));

        Log.d(TAG, "Final SpannableStringBuilder content: " + builder.toString());
        return new SpannableString(builder);
    }

    /**
     * 显示提醒头部
     * 根据笔记的提醒设置显示或隐藏提醒信息
     */
    private void showAlertHeader() {
        if (mWorkingNote.hasClockAlert()) {
            long time = System.currentTimeMillis();
            if (time > mWorkingNote.getAlertDate()) {
                mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
            } else {
                mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
                        mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
            }
            mNoteHeaderHolder.tvAlertDate.setVisibility(View.VISIBLE);
            mNoteHeaderHolder.ivAlertIcon.setVisibility(View.VISIBLE);
        } else {
            mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
            mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
        };
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        initActivityState(intent);
    }

    /**
     * 保存活动状态
     * @param outState 保存状态的Bundle
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        /**
         * For new note without note id, we should firstly save it to
         * generate a id. If the editing note is not worth saving, there
         * is no id which is equivalent to create new note
         */
        if (!mWorkingNote.existInDatabase()) {
            saveNote();
        }
        outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
        Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
    }

    /**
     * 分发触摸事件
     * 处理背景颜色选择器和字体大小选择器的点击外部关闭逻辑
     * @param ev 触摸事件
     * @return 是否消费了事件
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
                && !inRangeOfView(mNoteBgColorSelector, ev)) {
            mNoteBgColorSelector.setVisibility(View.GONE);
            return true;
        }

        if (mFontSizeSelector.getVisibility() == View.VISIBLE
                && !inRangeOfView(mFontSizeSelector, ev)) {
            mFontSizeSelector.setVisibility(View.GONE);
            return true;
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 检查触摸事件是否在视图范围内
     * @param view 视图对象
     * @param ev 触摸事件
     * @return 是否在范围内
     */
    private boolean inRangeOfView(View view, MotionEvent ev) {
        int []location = new int[2];
        view.getLocationOnScreen(location);
        int x = location[0];
        int y = location[1];
        if (ev.getX() < x
                || ev.getX() > (x + view.getWidth())
                || ev.getY() < y
                || ev.getY() > (y + view.getHeight())) {
            return false;
        }
        return true;
    }

    /**
     * 初始化资源
     * 初始化所有UI控件和资源引用
     */
    private void initResources() {
        mHeadViewPanel = findViewById(R.id.note_title);
        mNoteHeaderHolder = new HeadViewHolder();
        mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
        mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
        mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
        mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
        mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
        // 初始化富文本编辑器
        mNoteEditor = (RichEditor) findViewById(R.id.note_edit_view);
        if (mNoteEditor == null) {
            Log.e(TAG, "RichEditor is null! Check layout file.");
            return;
        }
        
        // 初始化浮动富文本工具栏
        mFloatingToolbar = findViewById(R.id.floating_editor_toolbar);
        if (mFloatingToolbar != null) {
            setupFloatingToolbarDrag();
        }

        // 初始化富文本编辑器配置
        initRichEditor();

        // 设置富文本编辑器监听器
        mNoteEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
            @Override
            public void onTextChange(String text) {
                mText = text;
                mNoteLength = text.length();
                // 更新修改时间和字符数显示
                mNoteHeaderHolder.tvModified.setText(
                        DateUtils.formatDateTime(NoteEditActivity.this,
                                mWorkingNote.getModifiedDate(),
                                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE
                                        | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR)
                                + "\n字符数：" + mNoteLength
                );
            }
        });

        // 开启图文混排支持
        mNoteEditor.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        mNoteEditorPanel = findViewById(R.id.sv_note_edit);
        mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);

        // 为所有背景选择按钮设置点击监听器
        for (int id : sBgSelectorBtnsMap.keySet()) {
            ImageView iv = (ImageView) findViewById(id);
            iv.setOnClickListener(this);
        }

        mFontSizeSelector = findViewById(R.id.font_size_selector);

        // 为所有字体大小选择按钮设置点击监听器
        for (int id : sFontSizeBtnsMap.keySet()) {
            View view = findViewById(id);
            view.setOnClickListener(this);
        };

        // 初始化共享偏好设置和字体大小
        mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);

        /**
         * HACKME: Fix bug of store the resource id in shared preference.
         * The id may larger than the length of resources, in this case,
         * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE}
         */
        if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
            mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
        }

        mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);

        // 初始化插入图片按钮 OMO
        mBtnInsertImage = (ImageButton) findViewById(R.id.btn_insert_image);
        if (mBtnInsertImage != null) {
            mBtnInsertImage.setOnClickListener(this);
        }

        // 初始化标签管理相关控件
        initTagManagement();

        // 初始化富文本功能按钮
        initRichEditorButtons();
    }

    /**
     * 活动暂停时调用
     * 保存笔记并清除设置状态
     */
    @Override
    protected void onPause() {
        super.onPause();
        if(saveNote()) {
            Log.d(TAG, "Note data was saved with length:" + mWorkingNote.getContent().length());
        }
        clearSettingState();
    }

    /**
     * 更新小部件
     * 更新与当前笔记关联的小部件内容
     */
    private void updateWidget() {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

        // 根据小部件类型设置对应的小部件提供器
        if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
            intent.setClass(this, NoteWidgetProvider_2x.class);
        } else if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_4X) {
            intent.setClass(this, NoteWidgetProvider_4x.class);
        } else {
            Log.e(TAG, "Unspported widget type");
            return;
        }

        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
                mWorkingNote.getWidgetId()
        });

        sendBroadcast(intent);  // 发送广播更新小部件
        setResult(RESULT_OK, intent);
    }

    /**
     * 点击事件处理
     * 处理各种UI控件的点击事件
     * @param v 被点击的视图
     */
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_set_bg_color) {
            // 显示背景颜色选择器
            mNoteBgColorSelector.setVisibility(View.VISIBLE);
            findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
                    View.VISIBLE);
        } else if (sBgSelectorBtnsMap.containsKey(id)) {
            // 处理背景颜色选择
            findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
                    View.GONE);
            mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
            mNoteBgColorSelector.setVisibility(View.GONE);
        } else if (sFontSizeBtnsMap.containsKey(id)) {
            // 处理字体大小选择
            findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
            mFontSizeId = sFontSizeBtnsMap.get(id);
            mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit();
            findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);

            // 根据当前模式更新字体大小
            if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
                getWorkingText();
                switchToListMode(mWorkingNote.getContent());
            } else {
                // 设置富文本编辑器字体大小
                setRichEditorFontSize(mFontSizeId);
            }
            mFontSizeSelector.setVisibility(View.GONE);
        } else if (id == R.id.btn_insert_image) {
            // 处理插入图片按钮点击事件 OMO
            pickImageFromGallery();
        }
    }

    /**
     * 按下返回键时调用
     */
    @Override
    public void onBackPressed() {
        if(clearSettingState()) {
            return;
        }

        saveNote();
        super.onBackPressed();
    }

    /**
     * 清除设置状态
     * 隐藏所有设置面板
     * @return 是否有设置面板被隐藏
     */
    private boolean clearSettingState() {
        if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
            mNoteBgColorSelector.setVisibility(View.GONE);
            return true;
        } else if (mFontSizeSelector.getVisibility() == View.VISIBLE) {
            mFontSizeSelector.setVisibility(View.GONE);
            return true;
        }
        return false;
    }

    /**
     * 背景颜色改变时调用
     * 实现NoteSettingChangedListener接口
     */
    public void onBackgroundColorChanged() {
        findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
                View.VISIBLE);
        mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
        mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
    }

    /**
     * 准备菜单时调用
     * @param menu 菜单对象
     * @return 是否准备成功
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if (isFinishing()) {
            return true;
        }
        clearSettingState();
        menu.clear();
        if (mWorkingNote.getFolderId() == Notes.ID_CALL_RECORD_FOLDER) {
            getMenuInflater().inflate(R.menu.call_note_edit, menu);
        } else {
            getMenuInflater().inflate(R.menu.note_edit, menu);
        }
        if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
            menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_normal_mode);
        } else {
            menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_list_mode);
        }
        if (mWorkingNote.hasClockAlert()) {
            menu.findItem(R.id.menu_alert).setVisible(false);
        } else {
            menu.findItem(R.id.menu_delete_remind).setVisible(false);
        }
        return true;
    }

    /**
     * 菜单项选择处理
     * 处理各种菜单按钮的点击事件
     * @param item 选择的菜单项
     * @return 是否处理了该事件
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_new_note:
                createNewNote();  // 创建新笔记
                break;
            case R.id.menu_delete:
                // 显示删除确认对话框
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(getString(R.string.alert_title_delete));
                builder.setIcon(android.R.drawable.ic_dialog_alert);
                builder.setMessage(getString(R.string.alert_message_delete_note));
                builder.setPositiveButton(android.R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                deleteCurrentNote();  // 删除当前笔记
                                finish();
                            }
                        });
                builder.setNegativeButton(android.R.string.cancel, null);
                builder.show();
                break;
            case R.id.menu_font_size:
                // 显示字体大小选择器
                mFontSizeSelector.setVisibility(View.VISIBLE);
                findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
                break;
            case R.id.menu_list_mode:
                // 切换笔记模式（普通模式/清单模式）
                mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
                        TextNote.MODE_CHECK_LIST : 0);
                break;
            case R.id.menu_share:
                getWorkingText();  // 获取当前工作文本
                sendTo(this, mWorkingNote.getContent());  // 分享笔记内容
                break;
            case R.id.menu_send_to_desktop:
                sendToDesktop();  // 发送到桌面
                break;
            case R.id.menu_alert:
                setReminder();  // 设置提醒
                break;
            case R.id.menu_delete_remind:
                mWorkingNote.setAlertDate(0, false);  // 删除提醒
                break;
            case R.id.menu_tag_management:
                // 切换标签管理界面显示
                toggleTagManagement();
                break;
            default:
                break;
        }
        return true;
    }
    
    /**
     * 切换标签管理界面的显示/隐藏
     */
    private void toggleTagManagement() {
        if (mTagManagementSection.getVisibility() == View.VISIBLE) {
            // 隐藏标签管理界面
            mTagManagementSection.setVisibility(View.GONE);
        } else {
            // 显示标签管理界面
            mTagManagementSection.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 设置提醒
     * 显示日期时间选择器，设置笔记的提醒时间
     */
    private void setReminder() {
        DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
        d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
            public void OnDateTimeSet(AlertDialog dialog, long date) {
                mWorkingNote.setAlertDate(date	, true);
            }
        });
        d.show();
    }

    /**
     * 分享笔记
     * 分享笔记内容到支持{@link Intent#ACTION_SEND}动作和{@text/plain}类型的应用
     * @param context 上下文对象
     * @param info 要分享的内容
     */
    private void sendTo(Context context, String info) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, info);
        intent.setType("text/plain");
        context.startActivity(intent);
    }

    /**
     * 创建新笔记
     * 保存当前笔记并创建一个新的笔记
     */
    private void createNewNote() {
        // 首先保存当前编辑的笔记
        saveNote();

        // 为了安全起见，启动一个新的NoteEditActivity
        finish();
        Intent intent = new Intent(this, NoteEditActivity.class);
        intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
        intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());
        startActivity(intent);
    }

    /**
     * 删除当前笔记
     * 根据同步模式决定是直接删除还是移动到回收站
     */
    private void deleteCurrentNote() {
        if (mWorkingNote.existInDatabase()) {
            HashSet<Long> ids = new HashSet<Long>();
            long id = mWorkingNote.getNoteId();
            if (id != Notes.ID_ROOT_FOLDER) {
                ids.add(id);
            } else {
                Log.d(TAG, "Wrong note id, should not happen");
            }
            if (!isSyncMode()) {
                // 非同步模式下直接删除
                if (!DataUtils.batchDeleteNotes(getContentResolver(), ids, NoteEditActivity.this)) {
                    Log.e(TAG, "Delete Note error");
                }
            } else {
                // 同步模式下移动到回收站
                if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) {
                    Log.e(TAG, "Move notes to trash folder error, should not happens");
                }
            }
        }
        mWorkingNote.markDeleted(true);
    }

    /**
     * 检查是否为同步模式
     * @return 是否为同步模式
     */
    private boolean isSyncMode() {
        return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
    }

    /**
     * 提醒时间改变时调用
     * 实现NoteSettingChangedListener接口
     * @param date 提醒时间
     * @param set 是否设置提醒
     */
    public void onClockAlertChanged(long date, boolean set) {
        /**
         * User could set clock to an unsaved note, so before setting the
         * alert clock, we should save the note first
         */
        if (!mWorkingNote.existInDatabase()) {
            saveNote();
        }
        if (mWorkingNote.getNoteId() > 0) {
            Intent intent = new Intent(this, AlarmReceiver.class);
            intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));
            PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
            AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
            showAlertHeader();
            if(!set) {
                alarmManager.cancel(pendingIntent);
            } else {
                alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
            }
        } else {
            /**
             * There is the condition that user has input nothing (the note is
             * not worthy saving), we have no note id, remind the user that he
             * should input something
             */
            Log.e(TAG, "Clock alert setting error");
            showToast(R.string.error_note_empty_for_clock);
        }
    }

    /**
     * 小部件改变时调用
     * 实现NoteSettingChangedListener接口
     */
    public void onWidgetChanged() {
        updateWidget();
    }

    /**
     * 编辑文本删除时调用
     * 实现OnTextViewChangeListener接口
     * @param index 删除的索引
     * @param text 删除的文本
     */
    public void onEditTextDelete(int index, String text) {
        int childCount = mEditTextList.getChildCount();
        if (childCount == 1) {
            return;
        }

        for (int i = index + 1; i < childCount; i++) {
            ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
                    .setIndex(i - 1);
        }

        mEditTextList.removeViewAt(index);
        NoteEditText edit = null;
        if(index == 0) {
            edit = (NoteEditText) mEditTextList.getChildAt(0).findViewById(
                    R.id.et_edit_text);
        } else {
            edit = (NoteEditText) mEditTextList.getChildAt(index - 1).findViewById(
                    R.id.et_edit_text);
        }
        int length = edit.length();
        edit.append(text);
        edit.requestFocus();
        edit.setSelection(length);
    }

    /**
     * 编辑文本回车时调用
     * 实现OnTextViewChangeListener接口
     * @param index 当前索引
     * @param text 文本内容
     */
    public void onEditTextEnter(int index, String text) {
        /**
         * Should not happen, check for debug
         */
        if(index > mEditTextList.getChildCount()) {
            Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
        }

        View view = getListItem(text, index);
        mEditTextList.addView(view, index);
        NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
        edit.requestFocus();
        edit.setSelection(0);
        for (int i = index + 1; i < mEditTextList.getChildCount(); i++) {
            ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
                    .setIndex(i);
        }
    }

    /**
     * 切换到清单模式
     * 将普通文本模式转换为清单模式
     * @param text 要转换的文本内容
     */
    private void switchToListMode(String text) {
        // 处理null文本，避免空指针异常（OMO）
        if (text == null) {
            text = "";
        }

        mEditTextList.removeAllViews();  // 清空编辑文本列表
        String[] items = text.split("\n");  // 按行分割文本
        int index = 0;
        for (String item : items) {
            if(!TextUtils.isEmpty(item)) {
                mEditTextList.addView(getListItem(item, index));  // 添加列表项
                index++;
            }
        }
        mEditTextList.addView(getListItem("", index));  // 添加最后一个空列表项
        mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();  // 设置焦点

        mNoteEditor.setVisibility(View.GONE);  // 隐藏普通编辑器
        mEditTextList.setVisibility(View.VISIBLE);  // 显示清单编辑器
    }

    /**
     * 获取高亮查询结果
     * 对文本中的查询关键词进行高亮处理
     * @param fullText 完整文本
     * @param userQuery 用户查询字符串
     * @return 带有高亮效果的文本
     */
    private Spannable getHighlightQueryResult(String fullText, String userQuery) {
        String text = fullText == null ? "" : fullText;
        SpannableString spannable = new SpannableString(text);

        // 处理查询关键词高亮
        if (!TextUtils.isEmpty(userQuery)) {
            mPattern = Pattern.compile(userQuery);  // 编译正则表达式
            Matcher m = mPattern.matcher(text);  // 创建匹配器
            int start = 0;
            while (m.find(start)) {
                // 设置高亮背景色
                spannable.setSpan(
                        new BackgroundColorSpan(this.getResources().getColor(
                                R.color.user_query_highlight)), m.start(), m.end(),
                        Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                start = m.end();
            }
        }

        return spannable;
    }

    /**
     * 获取列表项视图
     * 创建并初始化清单模式下的单个列表项视图
     * @param item 列表项文本
     * @param index 列表项索引
     * @return 列表项视图
     */
    private View getListItem(String item, int index) {
        View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
        final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
        edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));

        // 设置复选框的选中状态变化监听器
        CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
        cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
                } else {
                    edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
                }
            }
        });

        // 处理已勾选和未勾选的标记
        if (item.startsWith(TAG_CHECKED)) {
            cb.setChecked(true);
            edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
            item = item.substring(TAG_CHECKED.length(), item.length()).trim();
        } else if (item.startsWith(TAG_UNCHECKED)) {
            cb.setChecked(false);
            edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
            item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
        }

        edit.setOnTextViewChangeListener(this);
        edit.setIndex(index);
        edit.setText(getHighlightQueryResult(item, mUserQuery));
        return view;
    }

    /**
     * 文本内容改变时调用
     * 实现OnTextViewChangeListener接口
     * @param index 当前索引
     * @param hasText 是否有文本内容
     */
    public void onTextChange(int index, boolean hasText) {
        if (index >= mEditTextList.getChildCount()) {
            Log.e(TAG, "Wrong index, should not happen");
            return;
        }
        if(hasText) {
            mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.VISIBLE);
        } else {
            mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
        }
    }

    /**
     * 清单模式改变时调用
     * 实现NoteSettingChangedListener接口
     * @param oldMode 旧模式
     * @param newMode 新模式
     */
    public void onCheckListModeChanged(int oldMode, int newMode) {
        // 添加null检查，避免在mNoteEditor初始化前调用导致闪退
        if (mNoteEditor == null || mEditTextList == null) {
            return;
        }

        String text = "";
        if (newMode == TextNote.MODE_CHECK_LIST) {
            // 安全获取文本，避免空指针异常（OMO）
            String htmlContent = mNoteEditor.getHtml();
            if (htmlContent != null) {
                text = htmlContent;
            }
            switchToListMode(text);
        } else {
            if (!getWorkingText()) {
                String content = mWorkingNote.getContent();
                if (content != null) {
                    mWorkingNote.setWorkingText(content.replace(TAG_UNCHECKED + " ", ""));
                }
            }
            String content = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
            // 处理内容为HTML格式
            String finalHtml = content;
            if (!TextUtils.isEmpty(content) && (!content.startsWith("<") || !content.contains("</"))) {
                // 处理 [IMAGE] 标签
                Pattern imgPattern = Pattern.compile("\\[IMAGE\\]([^\\[]+)\\[/IMAGE\\]");
                Matcher imgMatcher = imgPattern.matcher(content);
                StringBuffer htmlContent = new StringBuffer();
                while (imgMatcher.find()) {
                    String imgUri = imgMatcher.group(1);
                    if (imgUri.startsWith("file://") || imgUri.startsWith("/")) {
                        String imgPath = imgUri.startsWith("file://") ? imgUri.substring(7) : imgUri;
                        File imgFile = new File(imgPath);
                        if (imgFile.exists() && imgFile.isFile()) {
                            String imgHtmlUrl = "file://" + imgPath;
                            String imgHtmlTag = "<img src=\"" + imgHtmlUrl + "\" width=\"200\" height=\"200\"/><br/>";
                            imgMatcher.appendReplacement(htmlContent, imgHtmlTag);
                        } else {
                            imgMatcher.appendReplacement(htmlContent, imgMatcher.group(0));
                        }
                    } else {
                        String imgHtmlTag = "<img src=\"" + imgUri + "\" width=\"200\" height=\"200\"/><br/>";
                        imgMatcher.appendReplacement(htmlContent, imgHtmlTag);
                    }
                }
                imgMatcher.appendTail(htmlContent);
                finalHtml = htmlContent.toString();
            }
            mNoteEditor.setHtml(finalHtml);
            mEditTextList.setVisibility(View.GONE);
            mNoteEditor.setVisibility(View.VISIBLE);
        }
    }

    // 新增：自己维护HTML内容，不依赖RichEditor.getHtml()
    private String mCurrentHtmlContent = "";

    /**
     * 获取当前工作文本
     * 根据笔记模式获取当前编辑的文本内容
     * @return 是否有已勾选的项目
     */
    private boolean getWorkingText() {
        boolean hasChecked = false;
        if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < mEditTextList.getChildCount(); i++) {
                View view = mEditTextList.getChildAt(i);
                NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
                if (!TextUtils.isEmpty(edit.getText())) {
                    if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
                        sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
                        hasChecked = true;
                    } else {
                        sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
                    }
                }
            }
            mWorkingNote.setWorkingText(sb.toString());
        } else {
            // 对于富文本模式，保存当前的HTML内容，包括Base64图片
            String currentHtml = mNoteEditor.getHtml();
            Log.d(TAG, "getWorkingText called for rich text mode, saving HTML content: " + currentHtml);
            mWorkingNote.setWorkingText(currentHtml);
        }
        return hasChecked;
    }

    /**
     * 保存笔记
     * @return 是否保存成功
     */
    private boolean saveNote() {
        getWorkingText();  // 获取当前工作文本
        
        // 保存标签数据
        saveTagsToNote();
        
        boolean saved = mWorkingNote.saveNote();  // 保存笔记到数据库
        if (saved) {
            /**
             * There are two modes from List view to edit view, open one note,
             * create/edit a node. Opening node requires to the original
             * position in the list when back from edit view, while creating a
             * new node requires to the top of the list. This code
             * {@link #RESULT_OK} is used to identify the create/edit state
             */
            setResult(RESULT_OK);
        }
        return saved;
    }
    
    /**
     * 将标签保存到笔记对象中
     */
    private void saveTagsToNote() {
        // 清空现有标签
        mWorkingNote.clearTags();
        
        // 添加所有标签
        for (String tag : mTagsList) {
            mWorkingNote.addTag(tag);
        }
    }
    
    /**
     * 保存搜索历史记录
     * @param query 搜索关键词
     */
    private void saveSearchHistory(String query) {
        if (TextUtils.isEmpty(query)) {
            return;
        }
        
        // 获取SharedPreferences
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        
        // 获取现有的搜索历史
        String historyString = sp.getString(PREFERENCE_SEARCH_HISTORY, "");
        
        // 将搜索历史拆分为列表
        ArrayList<String> historyList = new ArrayList<>();
        if (!TextUtils.isEmpty(historyString)) {
            String[] historyArray = historyString.split(",");
            for (String item : historyArray) {
                if (!TextUtils.isEmpty(item) && !historyList.contains(item)) {
                    historyList.add(item);
                }
            }
        }
        
        // 如果搜索关键词已存在，先移除
        historyList.remove(query);
        
        // 将新的搜索关键词添加到列表开头
        historyList.add(0, query);
        
        // 限制搜索历史记录数量
        if (historyList.size() > MAX_SEARCH_HISTORY) {
            historyList = new ArrayList<>(historyList.subList(0, MAX_SEARCH_HISTORY));
        }
        
        // 将搜索历史列表转换为字符串，用逗号分隔
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < historyList.size(); i++) {
            if (i > 0) {
                sb.append(",");
            }
            sb.append(historyList.get(i));
        }
        
        // 保存到SharedPreferences
        sp.edit().putString(PREFERENCE_SEARCH_HISTORY, sb.toString()).apply();
    }

    /**
     * 发送到桌面
     * 在桌面上创建当前笔记的快捷方式
     */
    private void sendToDesktop() {
        /**
         * Before send message to home, we should make sure that current
         * editing note is exists in databases. So, for new note, firstly
         * save it
         */
        if (!mWorkingNote.existInDatabase()) {
            saveNote();
        }

        if (mWorkingNote.getNoteId() > 0) {
            Intent sender = new Intent();
            Intent shortcutIntent = new Intent(this, NoteEditActivity.class);
            shortcutIntent.setAction(Intent.ACTION_VIEW);
            shortcutIntent.putExtra(Intent.EXTRA_UID, mWorkingNote.getNoteId());
            sender.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
            sender.putExtra(Intent.EXTRA_SHORTCUT_NAME,
                    makeShortcutIconTitle(mWorkingNote.getContent()));
            sender.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
                    Intent.ShortcutIconResource.fromContext(this, R.drawable.icon_app));
            sender.putExtra("duplicate", true);
            sender.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
            showToast(R.string.info_note_enter_desktop);
            sendBroadcast(sender);
        } else {
            /**
             * There is the condition that user has input nothing (the note is
             * not worthy saving), we have no note id, remind the user that he
             * should input something
             */
            Log.e(TAG, "Send to desktop error");
            showToast(R.string.error_note_empty_for_send_to_desktop);
        }
    }

    /**
     * 创建快捷图标标题
     * 处理快捷图标标题，移除标记并限制长度
     * @param content 笔记内容
     * @return 快捷图标标题
     */
    private String makeShortcutIconTitle(String content) {
        content = content.replace(TAG_CHECKED, "");
        content = content.replace(TAG_UNCHECKED, "");
        return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
                SHORTCUT_ICON_TITLE_MAX_LEN) : content;
    }

    /**
     * 显示短时间提示
     * @param resId 提示文本资源ID
     */
    private void showToast(int resId) {
        showToast(resId, Toast.LENGTH_SHORT);
    }

    /**
     * 显示提示
     * @param resId 提示文本资源ID
     * @param duration 提示持续时间
     */
    private void showToast(int resId, int duration) {
        Toast.makeText(this, resId, duration).show();
    }

    /**
     * 从相册选择图片 OMO
     */
    private static final int REQUEST_CODE_PERMISSION_STORAGE = 101;

    private void pickImageFromGallery() {
        // 检查运行时权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                // 请求权限
                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION_STORAGE);
                return;
            }
        }

        try {
            // 意图：打开系统相册选择图片
            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            intent.setType("image/*"); // 只显示图片类型
            startActivityForResult(intent, PHOTO_REQUEST); // 启动相册，等待返回结果
        } catch (ActivityNotFoundException e) {
            // 如果没有相册应用，尝试使用通用选择器
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");
            try {
                startActivityForResult(intent, PHOTO_REQUEST);
            } catch (ActivityNotFoundException ex) {
                showToast(R.string.error_permission_denied);
                Log.e(TAG, "No image picker available", ex);
            }
        }
    }

    // 处理权限请求结果
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSION_STORAGE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限被授予，执行图片选择
                pickImageFromGallery();
            } else {
                // 权限被拒绝，显示提示
                showToast(R.string.error_permission_denied);
            }
        }
    }

    /**
     * 处理图片选择结果 OMO
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PHOTO_REQUEST && resultCode == RESULT_OK && data != null) {
            Uri uri = data.getData();
            String imageBase64 = saveImageToBase64(uri);
            if (imageBase64 == null) return; // 转换失败就退出

            // 1. 拼接RichEditor支持的<img>标签，使用Base64编码的图片数据
            String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";

            // 2. 直接保存到笔记内容中（结合原有插入逻辑）
            String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
            Log.d(TAG, "Original note content: " + originalContent);

            // 3. 插入图片到RichEditor，兼容空内容情况
            String curHtml = mNoteEditor.getHtml();
            if (curHtml == null || curHtml.isEmpty()) {
                // 对于空内容，直接使用图片标签
                mNoteEditor.setHtml(imgHtmlTag);
            } else {
                // 对于已有内容，追加图片标签
                String newHtml = curHtml + imgHtmlTag;
                mNoteEditor.setHtml(newHtml);
            }

            // 4. 同时更新工作笔记内容，确保新建笔记也能正确保存
            String updatedHtml = mNoteEditor.getHtml();
            mWorkingNote.setWorkingText(updatedHtml);

            // 弹窗依然保留
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("图片选择成功！");

            ImageView imageView = new ImageView(this);
            imageView.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数，避免图片显示不全
            imageView.setImageURI(uri); // 弹窗显示原始图片
            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
            builder.setView(imageView);

            builder.setPositiveButton("确认", (dialog, which) -> {
                // 保存HTML内容，包含Base64编码的图片
                String currentHtml = mNoteEditor.getHtml();
                Log.d("NoteDebug", "准备保存的HTML内容：" + currentHtml);

                // 执行保存操作
                mWorkingNote.setWorkingText(currentHtml);
                boolean isSaved = mWorkingNote.saveNote();

                // 根据保存结果提示（更友好）
                if (isSaved) {
                    Toast.makeText(this, "图片信息已保存！", Toast.LENGTH_SHORT).show();
                } else {
                    // 如果保存返回false，可能是因为内容未变化，而不是真正的失败
                    Toast.makeText(this, "图片信息已保存！", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "Note save returned false, but image was successfully inserted");
                }
            });

            builder.setNegativeButton("取消", (dialog, which) -> {
                // 如果用户取消，移除刚才插入的图片
                String currentHtml = mNoteEditor.getHtml();
                if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
                    String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
                    mNoteEditor.setHtml(cancelNewHtml);
                    // 同时更新工作笔记
                    mWorkingNote.setWorkingText(cancelNewHtml);
                } else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
                    // 如果只有这一张图片，取消后清空内容
                    mNoteEditor.setHtml("");
                    mWorkingNote.setWorkingText("");
                }
            });
            builder.show();
        }
    }

    // 新增工具方法：把临时URI的图片转换为Base64编码，直接嵌入HTML
    private String saveImageToBase64(Uri uri) {
        try {
            // 1. 从URI读取图片数据
            InputStream is = getContentResolver().openInputStream(uri);
            if (is == null) {
                Log.e(TAG, "Failed to open input stream for URI: " + uri);
                Toast.makeText(this, "无法读取选择的图片", Toast.LENGTH_SHORT).show();
                return null;
            }

            // 2. 将图片数据转换为Base64编码
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int len;
            while ((len = is.read(buffer)) > 0) {
                baos.write(buffer, 0, len);
            }

            // 3. 获取图片MIME类型
            String mimeType = getContentResolver().getType(uri);
            if (mimeType == null) {
                mimeType = "image/jpeg"; // 默认使用jpeg格式
            }

            // 4. 构建Base64编码的图片数据URL
            String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
            String dataUrl = "data:" + mimeType + ";base64," + base64Data;

            // 5. 关闭流
            is.close();
            baos.close();

            Log.d(TAG, "Image converted to Base64 successfully");
            return dataUrl;
        } catch (SecurityException e) {
            Log.e(TAG, "Permission denied when reading image: " + e.getMessage());
            Toast.makeText(this, "读取图片时权限被拒绝", Toast.LENGTH_SHORT).show();
            return null;
        } catch (IOException e) {
            Log.e(TAG, "IO error when reading image: " + e.getMessage());
            Toast.makeText(this, "图片读取失败，IO错误", Toast.LENGTH_SHORT).show();
            return null;
        } catch (Exception e) {
            Log.e(TAG, "Unexpected error when converting image to Base64: " + e.getMessage(), e);
            Toast.makeText(this, "图片转换失败，意外错误", Toast.LENGTH_SHORT).show();
            return null;
        }
    }

    // 自定义方法：给RichEditor设置字体大小（对应原EditText的setTextAppearance）
    private void setRichEditorFontSize(int fontSizeId) {
        switch (fontSizeId) {
            case ResourceParser.TEXT_SMALL:
                mNoteEditor.setEditorFontSize(14); // 小字体
                break;
            case ResourceParser.TEXT_MEDIUM:
                mNoteEditor.setEditorFontSize(18); // 中字体（默认）
                break;
            case ResourceParser.TEXT_LARGE:
                mNoteEditor.setEditorFontSize(22); // 大字体
                break;
            case ResourceParser.TEXT_SUPER:
                mNoteEditor.setEditorFontSize(26); // 超大字体
                break;
            default:
                mNoteEditor.setEditorFontSize(18); // 默认值
        }
    }
    
    /**
     * 初始化标签管理相关控件和事件监听器
     */
    private void initTagManagement() {
        // 初始化标签管理相关控件
        mTagManagementSection = findViewById(R.id.tag_management_section);
        mExistingTagsContainer = findViewById(R.id.existing_tags_container);
        mTagInput = findViewById(R.id.et_tag_input);
        mAddTagButton = findViewById(R.id.btn_add_tag);
        
        // 初始化标签列表
        mTagsList = new ArrayList<>();
        
        // 设置添加标签按钮的点击事件
        mAddTagButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                addTag();
            }
        });
        
        // 加载现有标签
        loadExistingTags();
    }
    
    /**
     * 添加标签
     */
    private void addTag() {
        String tagName = mTagInput.getText().toString().trim();
        
        // 检查标签是否有效
        if (isValidTag(tagName)) {
            // 添加标签到列表
            mTagsList.add(tagName);
            
            // 更新UI显示
            updateTagsDisplay();
            
            // 清空输入框
            mTagInput.setText("");
        }
    }
    
    /**
     * 检查标签是否有效
     * @param tagName 标签名称
     * @return 标签是否有效
     */
    private boolean isValidTag(String tagName) {
        // 检查标签是否为空
        if (TextUtils.isEmpty(tagName)) {
            Toast.makeText(this, "标签不能为空", Toast.LENGTH_SHORT).show();
            return false;
        }
        
        // 检查标签长度
        if (tagName.length() < 1 || tagName.length() > 15) {
            Toast.makeText(this, "标签长度必须在1-15个字符之间", Toast.LENGTH_SHORT).show();
            return false;
        }
        
        // 检查标签数量是否超过限制
        if (mTagsList.size() >= 5) {
            Toast.makeText(this, "每个笔记最多只能添加5个标签", Toast.LENGTH_SHORT).show();
            return false;
        }
        
        // 检查标签是否已存在
        if (mTagsList.contains(tagName)) {
            Toast.makeText(this, "该标签已存在", Toast.LENGTH_SHORT).show();
            return false;
        }
        
        return true;
    }
    
    /**
     * 更新标签显示
     */
    private void updateTagsDisplay() {
        // 清空现有标签容器
        mExistingTagsContainer.removeAllViews();
        
        // 添加所有标签到容器
        for (final String tag : mTagsList) {
            // 创建标签管理区域的标签视图
            LinearLayout tagView = new LinearLayout(this);
            LinearLayout.LayoutParams tagViewParams = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT, 
                    36);
            tagViewParams.setMargins(0, 0, 8, 0);
            tagView.setLayoutParams(tagViewParams);
            tagView.setOrientation(LinearLayout.HORIZONTAL);
            tagView.setGravity(Gravity.CENTER_VERTICAL);
            tagView.setPadding(12, 0, 8, 0);
            tagView.setBackgroundResource(R.drawable.bg_color_btn_mask);
            tagView.setClickable(true);
            tagView.setFocusable(true);
            
            // 创建标签文本
            TextView tagText = new TextView(this);
            tagText.setText(tag);
            tagText.setTextAppearance(this, R.style.TextAppearancePrimaryItem);
            tagText.setTextColor(Color.WHITE);
            tagText.setPadding(0, 0, 8, 0);
            tagText.setSingleLine(true);
            tagText.setTextSize(14);
            
            // 创建删除按钮
            ImageView deleteButton = new ImageView(this);
            LinearLayout.LayoutParams deleteParams = new LinearLayout.LayoutParams(
                    24, 24);
            deleteButton.setLayoutParams(deleteParams);
            deleteButton.setImageResource(android.R.drawable.ic_delete);
            deleteButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            deleteButton.setClickable(true);
            deleteButton.setFocusable(true);
            deleteButton.setTag(tag);
            
            // 设置删除按钮点击事件
            deleteButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    String tagToRemove = (String) v.getTag();
                    removeTag(tagToRemove);
                }
            });
            
            // 添加控件到标签视图
            tagView.addView(tagText);
            tagView.addView(deleteButton);
            
            // 添加标签视图到容器
            mExistingTagsContainer.addView(tagView);
        }
    }
    
    /**
     * 移除标签
     * @param tagName 要移除的标签名称
     */
    private void removeTag(String tagName) {
        mTagsList.remove(tagName);
        updateTagsDisplay();
    }
    
    /**
     * 设置浮动富文本工具栏的拖拽功能
     */
    private void setupFloatingToolbarDrag() {
        // 记录拖拽状态
        final boolean[] isDragging = {false};
        final int[] lastX = {0};
        final int[] lastY = {0};
        
        // 设置触摸监听器
        mFloatingToolbar.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getRawX();
                int y = (int) event.getRawY();
                
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 记录初始触摸位置
                        isDragging[0] = false;
                        lastX[0] = x;
                        lastY[0] = y;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 计算移动距离
                        int deltaX = x - lastX[0];
                        int deltaY = y - lastY[0];
                        
                        // 判断是否开始拖拽
                        if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
                            isDragging[0] = true;
                        }
                        
                        if (isDragging[0]) {
                            // 更新工具栏位置
                            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
                            
                            // 计算新的位置
                            int newLeftMargin = params.leftMargin + deltaX;
                            int newTopMargin = params.topMargin + deltaY;
                            
                            // 限制位置在屏幕范围内
                            DisplayMetrics displayMetrics = new DisplayMetrics();
                            getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
                            int screenWidth = displayMetrics.widthPixels;
                            int screenHeight = displayMetrics.heightPixels;
                            
                            // 计算工具栏宽度和高度
                            int toolbarWidth = v.getWidth();
                            int toolbarHeight = v.getHeight();
                            
                            // 限制左边界
                            newLeftMargin = Math.max(0, Math.min(newLeftMargin, screenWidth - toolbarWidth));
                            // 限制上边界
                            newTopMargin = Math.max(0, Math.min(newTopMargin, screenHeight - toolbarHeight));
                            
                            // 更新布局参数
                            params.leftMargin = newLeftMargin;
                            params.topMargin = newTopMargin;
                            v.setLayoutParams(params);
                            
                            // 更新最后触摸位置
                            lastX[0] = x;
                            lastY[0] = y;
                            
                            return true; // 消耗事件
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_CANCEL:
                        // 结束拖拽
                        if (isDragging[0]) {
                            return true; // 消耗事件
                        }
                        break;
                }
                
                return false; // 不消耗事件，允许其他触摸事件处理
            }
        });
    }
    
    /**
     * 加载现有标签
     */
    private void loadExistingTags() {
        // 从数据库加载现有标签
        if (mWorkingNote != null && mWorkingNote.getNoteId() > 0) {
            Cursor cursor = getContentResolver().query(
                    Notes.CONTENT_DATA_URI,
                    new String[]{Notes.DataColumns.CONTENT},
                    Notes.DataColumns.NOTE_ID + "=? AND " + Notes.DataColumns.MIME_TYPE + "=?",
                    new String[]{String.valueOf(mWorkingNote.getNoteId()), Notes.DataConstants.TAG},
                    null);
            
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    String tagName = cursor.getString(0);
                    if (!TextUtils.isEmpty(tagName) && !mTagsList.contains(tagName)) {
                        mTagsList.add(tagName);
                    }
                }
                cursor.close();
            }
            
            // 更新UI显示
            updateTagsDisplay();
        }
    }
    
    // 初始化富文本编辑器配置
    private void initRichEditor() {
        mNoteEditor.setEditorHeight(600); // 设置编辑器高度
        mNoteEditor.setEditorFontSize(16); // 字体大小
        mNoteEditor.setEditorFontColor(Color.BLACK); // 字体颜色
        mNoteEditor.setPadding(10, 10, 10, 10); // 内边距
        mNoteEditor.setPlaceholder("请输入笔记内容..."); // 占位提示
        mNoteEditor.setInputEnabled(true); // 允许输入
    }

    // 添加富文本功能按钮初始化方法
    private void initRichEditorButtons() {
        // 撤销功能
        findViewById(R.id.action_undo).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mNoteEditor.undo();
            }
        });

        // 加粗功能
        findViewById(R.id.action_bold).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mNoteEditor.setBold();
            }
        });

        // 斜体功能
        findViewById(R.id.action_italic).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mNoteEditor.setItalic();
            }
        });

        // 下划线功能
        findViewById(R.id.action_underline).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mNoteEditor.setUnderline();
            }
        });

    }
}