/*
 * 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.annotation.SuppressLint;
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.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;

import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
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;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//便签编辑类,实现便签编辑有关的活动，实现点击监听、便签设置更改监听、文字更改监听接口
public class NoteEditActivity extends Activity implements OnClickListener,
        NoteSettingChangedListener, OnTextViewChangeListener {
    private class HeadViewHolder {
        public TextView tvModified;

        public ImageView ivAlertIcon;

        public TextView tvAlertDate;

        public ImageView ibSetBgColor;
    }

    //使用map进行数据存储，put将键和值相连
    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);
    }

    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);
    }

    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);
    }

    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 HeadViewHolder mNoteHeaderHolder;

    private View mHeadViewPanel; //表头操作

    private View mNoteBgColorSelector; //颜色操作

    private View mFontSizeSelector; //字体操作

    private EditText mNoteEditor; //文本操作

    private View mNoteEditorPanel;

    private Button mSetType;//////////////////////////////////////////
    private WorkingNote mWorkingNote; //初始化正在工作便签

    private SharedPreferences mSharedPrefs;
    private int mFontSizeId;

    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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.note_edit); //设置背景

        if (savedInstanceState == null && !initActivityState(getIntent())) { //初始化活动状态
            finish();
            return;
        }
        initResources(); //初始化资源
    }

    /**
     * Current activity may be killed when the memory is low. Once it is killed, for another time
     * user load this activity, we should restore the former state
     */

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) { //Activity暂停状态到恢复式被调用
        super.onRestoreInstanceState(savedInstanceState);
        // 恢复之前保存的状态
        if (savedInstanceState != null && savedInstanceState.containsKey(Intent.EXTRA_UID)) {
            // 构建一个带有 ACTION_VIEW 的 Intent，并传递之前保存的笔记id
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.putExtra(Intent.EXTRA_UID, savedInstanceState.getLong(Intent.EXTRA_UID));
            // 初始化Activity的工作状态
            if (!initActivityState(intent)) {
                // 如果初始化失败，则结束当前Activity
                finish();
                return;
            }
            Log.d(TAG, "Restoring from killed activity");
        }
    }

    private boolean initActivityState(Intent intent) {
        // 初始化工作状态
        mWorkingNote = null;
        if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
            // 如果用户指定了ACTION_VIEW但没有提供id，则跳转到NotesListActivity
            long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
            mUserQuery = "";
    
            // 从搜索结果开始
            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)) {
                // 如果数据库中不存在指定的笔记，则跳转到NotesListActivity并显示错误信息
                Intent jump = new Intent(this, NotesListActivity.class);
                startActivity(jump);
                showToast(R.string.error_note_not_exist);
                finish();
                return false;
            } else {
                // 加载指定id的笔记
                mWorkingNote = WorkingNote.load(this, noteId);
                if (mWorkingNote == null) {
                    Log.e(TAG, "load note failed with note id" + noteId);
                    finish();
                    return false;
                }
            }
            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())) {
            // 新建笔记
            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));
    
            // 解析来电记录笔记
            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) {
                    // 加载指定id的来电记录笔记
                    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);
            }
    
            getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
                            | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        } else {
            // 如果Intent没有指定操作，则不应该支持该Intent，记录错误并关闭当前Activity
            Log.e(TAG, "Intent not specified action, should not support");
            finish();
            return false;
        }
        // 设置工作状态改变监听器并返回true表示初始化成功
        mWorkingNote.setOnSettingStatusChangedListener(this);
        return true;
    }

@Override
protected void onResume() { //进入交互状态时被调用
    super.onResume();
    initNoteScreen(); // 初始化笔记界面
}

private void initNoteScreen() {
    // 设置笔记编辑器的文本外观
    mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));

    // 根据工作笔记的模式进行不同的处理
    if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
        // 如果是清单模式，将编辑器切换到清单模式
        switchToListMode(mWorkingNote.getContent());
    } else {
        // 如果不是清单模式，将编辑器的文本设置为工作笔记的内容
        mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
        // 将光标设置在文本末尾
        mNoteEditor.setSelection(mNoteEditor.getText().length());
    }

    // 隐藏背景选择器中当前选中的项
    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(); // 显示提醒信息（如果有）
}

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); //更新状态
}

@Override
protected void onSaveInstanceState(Bundle outState) { //在即将被暂停或销毁时调用
    super.onSaveInstanceState(outState);
    
    /**
     * 如果编辑的笔记尚未在数据库中存在（没有ID），我们先保存它以生成一个ID。
     * 如果正在编辑的笔记不值得保存，则没有ID等同于创建新的笔记。
     */
    if (!mWorkingNote.existInDatabase()) {
        saveNote();
    }
    
    outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
    Log.d(TAG, "保存正在编辑的笔记ID：" + mWorkingNote.getNoteId() + "，onSaveInstanceState");
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) { //分发触摸事件，传递给View
    // 如果笔记背景颜色选择器可见，并且触摸事件的位置不在选择器内，隐藏选择器并返回true
    if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
            && !inRangeOfView(mNoteBgColorSelector, ev)) {
        mNoteBgColorSelector.setVisibility(View.GONE);
        return true;
    }

    // 如果字体大小选择器可见，并且触摸事件的位置不在选择器内，隐藏选择器并返回true
    if (mFontSizeSelector.getVisibility() == View.VISIBLE
            && !inRangeOfView(mFontSizeSelector, ev)) {
        mFontSizeSelector.setVisibility(View.GONE);
        return true;
    }
    
    // 如果触摸事件位置没有被处理，则调用父类的dispatchTouchEvent方法处理事件
    return super.dispatchTouchEvent(ev);
}

/**
 * 检查触摸事件的位置是否在给定View内部
 * 
 * @param view 要检查的View
 * @param ev 触摸事件
 * @return 触摸事件位置是否在View内部
 */
private boolean inRangeOfView(View view, MotionEvent ev) { //检查边界
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    int x = location[0];
    int y = location[1];
    
    // 如果触摸事件的位置超出了View的边界，则返回false
    if (ev.getX() < x
            || ev.getX() > (x + view.getWidth())
            || ev.getY() < y
            || ev.getY() > (y + view.getHeight())) {
        return false;
    }
    
    return true;
}

@SuppressLint("SetTextI18n")
private void initResources() {
    // 初始化控件和资源

    // 获取布局中的note_title并赋值给mHeadViewPanel
    mHeadViewPanel = findViewById(R.id.note_title);

    // 创建HeadViewHolder实例
    mNoteHeaderHolder = new HeadViewHolder();
    // 获取布局中的tv_modified_date并赋值给mNoteHeaderHolder中的tvModified
    mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
    // 获取布局中的iv_alert_icon并赋值给mNoteHeaderHolder中的ivAlertIcon
    mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon);
    // 获取布局中的tv_alert_date并赋值给mNoteHeaderHolder中的tvAlertDate
    mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date);
    // 获取布局中的btn_set_bg_color并赋值给mNoteHeaderHolder中的ibSetBgColor
    mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
    // 设置ibSetBgColor的点击事件监听器为当前Activity(this)
    mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);


    mSetType = (Button) findViewById(R.id.btn_SetType); //设置一个按钮表示设置便签类型
    if (Objects.equals(mWorkingNote.getNoteType(), "0")) { //如果当前便签无类型
        mSetType.setText("SetType"); //将文本设置为SetType
    }
    else {
        mSetType.setText(mWorkingNote.getNoteType()); //有类型则设置为当前类型
    }
    //String ss=mWorkingNote.getNoteType();
    mSetType.setOnClickListener(this);

    // 获取布局中的note_edit_view并赋值给mNoteEditor
    mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
    // 获取布局中的sv_note_edit并赋值给mNoteEditorPanel
    mNoteEditorPanel = findViewById(R.id.sv_note_edit);

    // 获取布局中的note_bg_color_selector并赋值给mNoteBgColorSelector
    mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
    // 遍历sBgSelectorBtnsMap中的按钮ID，并为每个按钮设置点击事件监听器为当前Activity(this)
    for (int id : sBgSelectorBtnsMap.keySet()) {
        ImageView iv = (ImageView) findViewById(id);
        iv.setOnClickListener(this);
    }

    // 获取布局中的font_size_selector并赋值给mFontSizeSelector
    mFontSizeSelector = findViewById(R.id.font_size_selector);
    // 遍历sFontSizeBtnsMap中的按钮ID，并为每个按钮设置点击事件监听器为当前Activity(this)
    for (int id : sFontSizeBtnsMap.keySet()) {
        View view = findViewById(id);
        view.setOnClickListener(this);
    };

    // 获取默认的SharedPreferences实例
    mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    // 从SharedPreferences中获取设置的字体大小ID，默认值为ResourceParser.BG_DEFAULT_FONT_SIZE
    mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
    /**
     * HACKME: 修复存储资源ID的共享偏好的bug。
     * ID可能大于资源的长度，在这种情况下，
     * 将其设置为ResourceParser.BG_DEFAULT_FONT_SIZE。
     */
    if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
        mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
    }

    // 获取布局中的note_edit_list并赋值给mEditTextList
    mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}

@Override
protected void onPause() {
    super.onPause();
    // 当Activity暂停时，保存笔记数据并输出日志
    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;
    }

    // 将工作笔记的小部件ID作为额外数据放入意图中
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
        mWorkingNote.getWidgetId()
    });

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

public void onClick(View v) {
    // 获取当前点击的控件的ID
    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);
        // 设置新的背景颜色ID给工作笔记
        mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
        // 隐藏背景颜色选择器
        mNoteBgColorSelector.setVisibility(View.GONE);
    } else if (id == R.id.btn_SetType) { //如果点击的是设置便签类型的按钮
        showTypeMenu(v); //展示便签类型菜单
    } else if (sFontSizeBtnsMap.containsKey(id)) {
        // 如果点击的是字体大小选择器中的一个按钮
        // 隐藏当前字体大小的选择项
        findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
        // 设置新的字体大小ID
        mFontSizeId = sFontSizeBtnsMap.get(id);
        // 将新的字体大小ID保存到SharedPreferences中
        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 {
            // 如果工作笔记不是待办事项模式
            // 设置文本编辑框的文本样式为选择的字体大小
            mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
        }
        // 隐藏字体大小选择器
        mFontSizeSelector.setVisibility(View.GONE);
    }
}

@Override
public void onBackPressed() {
    // 当返回按钮按下时
    if (clearSettingState()) {
        // 如果当前状态是设置状态，清除设置状态并返回
        return;
    }

    // 保存工作笔记
    saveNote();
    super.onBackPressed();
}
private void showTypeMenu(View view) { //展示选择便签类型的菜单
    // View当前PopupMenu显示的相对View的位置
    PopupMenu popupMenu = new PopupMenu(this, view);
    // menu布局
    popupMenu.getMenuInflater().inflate(R.menu.note_type, popupMenu.getMenu()); //获取menu中的xml资源
    // menu的item点击事件
    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            Toast.makeText(getApplicationContext(), item.getTitle(), Toast.LENGTH_SHORT).show();
            if(item.getItemId() == R.id.person) { //若选择的person
                mWorkingNote.setNoteType("个人");
                mWorkingNote.setBgColorId(ResourceParser.BLUE);//顺便更换对应背景颜色
                mSetType.setText("个人"); //设置按钮文本
            }else if (item.getItemId() == R.id.family) {
                mWorkingNote.setNoteType("家庭");
                mWorkingNote.setBgColorId(ResourceParser.YELLOW);
                mSetType.setText("家庭");
            }else if (item.getItemId() == R.id.work) {
                mWorkingNote.setNoteType("工作");
                mWorkingNote.setBgColorId(ResourceParser.GREEN);
                mSetType.setText("工作");
            }
            return false;
        }
    });
    // PopupMenu关闭事件
    popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
        @Override
        public void onDismiss(PopupMenu menu) {
            Toast.makeText(getApplicationContext(), "关闭PopupMenu", Toast.LENGTH_SHORT).show();
        }
    });
    popupMenu.show();
}

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;
}

public void onBackgroundColorChanged() {
    // 根据当前工作笔记的背景颜色ID显示相应的选择项
    findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(View.VISIBLE);
    // 设置工作笔记编辑面板的背景颜色为当前工作笔记的背景颜色资源ID
    mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
    // 设置工作笔记标题栏的背景颜色为当前工作笔记的标题背景资源ID
    mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
}

@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;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) { //响应用户在菜单中选择菜单项的操作
    int itemId = item.getItemId();
    if (itemId == R.id.menu_new_note) {
        // 当点击菜单项“新建笔记”时
        createNewNote();
    } else if (itemId == 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();
    } else if (itemId == R.id.menu_font_size) {
        // 当点击菜单项“字体大小”时
        // 显示字体大小选择器，并根据当前字体大小ID显示相应的选择项
        mFontSizeSelector.setVisibility(View.VISIBLE);
        findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
    } else if (itemId == R.id.menu_list_mode) {
        // 当点击菜单项“模式切换”时
        // 切换工作笔记的待办事项模式
        mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
                TextNote.MODE_CHECK_LIST : 0);
    } else if (itemId == R.id.menu_share) {
        // 当点击菜单项“分享”时
        // 获取当前工作文本并进行分享
        getWorkingText();
        sendTo(this, mWorkingNote.getContent());
    } else if (itemId == R.id.menu_send_to_desktop) {
        // 当点击菜单项“发送到桌面”时
        sendToDesktop();
    } else if (itemId == R.id.menu_alert) {
        // 当点击菜单项“提醒”时
        // 设置闹钟提醒
        setReminder();
    } else if (itemId == R.id.menu_delete_remind) {
        // 当点击菜单项“删除提醒”时
        // 清除工作笔记的提醒日期和提醒标志
        mWorkingNote.setAlertDate(0, false);
    }
    return true;
}

    private void setReminder() {
/*
 * 这段 Java 代码实现了一个名为 `setReminder()` 的方法，用于设置笔记的提醒功能。以下是对该方法的解释：
1. 首先，创建一个 `DateTimePickerDialog` 对象 `d`，用于显示日期时间选择对话框。
2. 通过传递 System.currentTimeMillis() 方法的返回值，设置初始日期时间选择为当前时间。
3. 将一个匿名的 `OnDateTimeSetListener` 实例设置给 `d`，用于在用户选择日期时间后响应事件。
4. 在 `OnDateTimeSet` 方法中，获取用户选择的日期时间，
并通过调用 `mWorkingNote` 对象的 `setAlertDate()` 方法设置笔记的提醒日期时间。
5. 最后，通过调用 `d` 对象的 `show()` 方法，显示日期时间选择对话框。
综上，该方法实现了通过日期时间选择对话框设置笔记提醒功能的功能，用户能够通过该对话框选择想要提醒的日期时间点。
在用户选择日期时间后，将所选日期时间点保存到 `mWorkingNote` 对象中，以实现笔记的提醒功能。
 */
        DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
        d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
            public void OnDateTimeSet(AlertDialog dialog, long date) {
                mWorkingNote.setAlertDate(date	, true);
            }
        });
        d.show();
    }

    /**
     * Share note to apps that support {@link Intent#ACTION_SEND} action
     * and {@text/plain} type
     */
    private void sendTo(Context context, String info) {
    /*
这是一个名为 `sendTo()` 的私有方法，用于发送信息。
该方法接受两个参数，一个是上下文（`context`），一个是要发送的信息（`info`）。
方法的具体步骤如下：
1. 创建一个 `Intent` 对象，使用 `Intent.ACTION_SEND` 动作。这表示我们要发送数据。
2. 使用 `intent.putExtra()` 方法将要发送的文本数据添加到 `Intent` 中。
键为 `Intent.EXTRA_TEXT`，值为 `info`，即要发送的信息内容。
3. 使用 `intent.setType()` 方法指定发送的数据类型为纯文本（"text/plain"）。
4. 调用 `context.startActivity(intent)` 启动该意图，从而触发系统选择合适的应用程序来处理发送操作。 
    */
     
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, info);
        intent.setType("text/plain");
        context.startActivity(intent);
    }

    private void createNewNote() {
        // Firstly, save current editing notes
        saveNote();

        // For safety, start a new 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);/*
        这段代码是一个方法 `createNewNote()` 的实现。下面是对代码的解释：
1. 首先，调用 `saveNote()` 方法保存当前正在编辑的笔记。
2. 为了安全起见，在开始新的笔记之前，调用 `finish()` 方法关闭当前的 Activity。
3. 创建一个新的 `Intent` 对象，将目标 Activity 设置为 `NoteEditActivity`（笔记编辑界面）。
4. 使用 `Intent.ACTION_INSERT_OR_EDIT` 设置操作，表示是插入或编辑操作。
5. 使用 `intent.putExtra()` 将当前笔记所属的文件夹的 ID 作为附加数据传递给 `NoteEditActivity`。
6. 最后，调用 `startActivity(intent)` 启动 `NoteEditActivity`。
这将打开一个新的笔记编辑界面，并根据传递的附加数据进行相应的操作。
        */
    }

    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)) {
                    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);
/*
 * 这段代码是一个方法 `deleteCurrentNote()` 的实现。下面是对代码的解释：
1. 首先，检查 `mWorkingNote` 是否存在于数据库中，即当前的笔记是否已经保存在数据库中。
2. 如果存在于数据库中，创建一个 `HashSet` 集合 `ids`，用于存储需要删除的笔记的 ID。
3. 获取当前笔记的 ID，并将其添加到 `ids` 集合中。
4. 检查当前笔记的 ID 是否等于 `Notes.ID_ROOT_FOLDER`，如果不是，将其添加到 `ids` 集合中。
5. 如果不是处于同步模式下（`isSyncMode()` 返回 `false`），
则调用 `DataUtils.batchDeleteNotes()` 方法批量删除数据库中的笔记。如果删除失败，打印错误日志信息。
6. 如果处于同步模式下，调用 `DataUtils.batchMoveToFolder()` 方法
将笔记批量移动到垃圾箱。如果移动失败，打印错误日志信息。
7. 调用 `mWorkingNote.markDeleted(true)` 方法，将当前笔记标记为已删除。
这段代码的作用是将当前的笔记标记为已删除，并根据不同的条件执行相应的操作：
如果不是同步模式，则删除数据库中的笔记；如果是同步模式，则将笔记移动到垃圾箱。
 */
    }

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

// 当闹钟提醒设置改变时的处理
public void onClockAlertChanged(long date, boolean set) {
    // 如果当前工作笔记不存在于数据库中，则保存笔记
    if (!mWorkingNote.existInDatabase()) {
        saveNote();
    }
    // 如果工作笔记的ID大于0，则继续处理
    if (mWorkingNote.getNoteId() > 0) {
        // 创建AlarmReceiver的Intent
        Intent intent = new Intent(this, AlarmReceiver.class);
        intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));
        // 创建用于广播的PendingIntent
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        // 获取AlarmManager实例
        AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
        // 显示提醒标题
        showAlertHeader();
        // 根据set参数判断是否设置或取消闹钟提醒
        if(!set) {
            alarmManager.cancel(pendingIntent); // 取消闹钟提醒
        } else {
            alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); // 设置闹钟提醒
        }
    } else {
        // 如果工作笔记ID小于等于0，记录错误并显示提示
        Log.e(TAG, "Clock alert setting error");
       showToast(R.string.error_note_empty_for_clock);
    }
}

// 当小部件改变时的处理
public void onWidgetChanged() {
    updateWidget(); // 更新小部件
}

// 当文本编辑框内容删除时的处理
public void onEditTextDelete(int index, String text) {
    int childCount = mEditTextList.getChildCount();
    // 如果子View数量为1，则直接返回
    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); // 设置光标位置
}

public void onEditTextEnter(int index, String text) {
    /**
     * 如果索引超出 mEditTextList 的范围，应该不会发生，进行调试检查
     */
    if(index > mEditTextList.getChildCount()) {
        Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
    }

    // 创建新的编辑框视图并添加到 mEditTextList 中指定的位置
    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);
    }
}

// 切换到列表模式的处理方法
private void switchToListMode(String text) {
    // 移除所有的编辑框视图
    mEditTextList.removeAllViews();
    // 将文本按换行符分割成字符串数组
    String[] items = text.split("\n");
    int index = 0;
    for (String item : items) {
        // 如果项不为空，则创建对应的编辑框视图并添加到 mEditTextList 中
        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);
}

// 获取包含用户查询结果高亮的 Spannable 对象
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
    SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
    if (!TextUtils.isEmpty(userQuery)) {
        mPattern = Pattern.compile(userQuery);
        Matcher m = mPattern.matcher(fullText);
        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)) {
        // 如果列表项以 "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)) {
        // 如果列表项以 "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;
}

/**
 * 当文本内容改变时的回调方法
 * @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);
    }
}

/**
 * 当待办事项模式变化时的回调方法
 * @param oldMode 旧的待办事项模式
 * @param newMode 新的待办事项模式
 */
public void onCheckListModeChanged(int oldMode, int newMode) {
    if (newMode == TextNote.MODE_CHECK_LIST) {
        // 如果新的模式是待办事项列表模式，则切换到列表模式
        switchToListMode(mNoteEditor.getText().toString());
    } else {
        if (!getWorkingText()) {
            // 如果工作文本为空，并且未保存的文本中包含 "unchecked" 标识，则将其移除
            mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", ""));
        }
        // 设置编辑框内容，并将用户查询结果高亮显示
        mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
        // 隐藏编辑框列表视图，显示笔记编辑视图
        mEditTextList.setVisibility(View.GONE);
        mNoteEditor.setVisibility(View.VISIBLE);
    }
}

    private boolean getWorkingText() {
/*
这是一个名为 `getWorkingText()` 的私有方法，返回一个布尔值。
该方法的作用是获取工作文本，具体步骤如下：
1. 首先，检查 `mWorkingNote` 对象的 `CheckListMode` 
是否为 `TextNote.MODE_CHECK_LIST`。如果是，则进入列表模式的处理逻辑。
2. 创建一个 `StringBuilder` 对象 `sb`，用于拼接文本。
3. 遍历 `mEditTextList` 中的子视图（可能是多个文本编辑框）：
   - 获取子视图中的 `NoteEditText` 对象，用于获取文本内容。
   - 如果 `edit.getText()` 不为空，表示该文本框有输入内容。
     - 如果相应的复选框 `CheckBox` 被选中（`isChecked()` 返回 `true`），
     将文本设为已选中状态，并向 `sb` 添加标记 `TAG_CHECKED`，文本内容，以及换行符。
       同时将 `hasChecked` 设为 `true`。
     - 否则，将文本设为未选中状态，并向 `sb` 添加标记 `TAG_UNCHECKED`，文本内容，以及换行符。
4. 将拼接好的文本 `sb.toString()` 设为 `mWorkingNote` 的工作文本。
5. 如果 `mWorkingNote` 的 `CheckListMode` 不是 `TextNote.MODE_CHECK_LIST`，
即非列表模式，则将 `mNoteEditor` 的文本内容设为 `mWorkingNote` 的工作文本。
6. 返回 `hasChecked`，该布尔值表示是否存在已选中的文本项。
 */
        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 {
            mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
        }
        return hasChecked;
    }

    private boolean saveNote() {
        getWorkingText();
        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 sendToDesktop() {
    /**
这段代码实现了一个名为 `sendToDesktop()` 的方法，用于将当前编辑的笔记发送到桌面上。
以下是对该方法的解释：
1. 首先，检查当前编辑的笔记 `mWorkingNote` 是否存在于数据库中。
如果笔记在数据库中不存在（即为新笔记），则调用 `saveNote()` 方法保存笔记。
2. 如果当前编辑的笔记已经存在于数据库中（即为已有的笔记），执行以下操作：
   - 创建一个 `Intent` 对象 `sender`。
   - 创建一个 `Intent` 对象 `shortcutIntent`，指定其启动目标为 `NoteEditActivity` 类。
   - 为 `shortcutIntent` 指定动作 `Intent.ACTION_VIEW`，表示要进行查看操作。
   - 通过 `putExtra()` 方法向 `shortcutIntent` 传递附加信息，包括笔记的唯一标识符（`NoteId`）。
   - 通过 `sender.putExtra()` 方法向 `sender` 传递附加信息，包括快捷方式的意图（`shortcutIntent`）、
   快捷方式的名称、快捷方式的图标资源和重复安装的标志等。
   - 通过设置 `sender` 的动作为 `"com.android.launcher.action.INSTALL_SHORTCUT"`，表示要安装快捷方式。
   - 调用 `showToast()` 方法显示一个消息提示框，提示用户笔记已进入桌面。
   - 调用 `sendBroadcast()` 方法发送广播，通知系统安装快捷方式。
3. 如果当前编辑的笔记不存在（即为没有输入内容的空笔记），
则记录一个错误日志并调用 `showToast()` 方法显示一个错误提示框，提醒用户输入内容。
4. 方法执行结束。
综上，该方法的功能是将当前编辑的笔记发送到桌面上，并根据笔记的状态进行相应的处理，如保存新笔记、创建快捷方式等。
         */
        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);
        }
    }

    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;
    }
    
    private void showToast(int resId) {
        // 显示一个短持续时间的Toast消息，消息内容为给定的资源ID的字符串
        showToast(resId, Toast.LENGTH_SHORT);
    }
    
    private void showToast(int resId, int duration) {
        // 显示一个具有自定义持续时间的Toast消息，消息内容为给定的资源ID的字符串
        // Toast消息在当前的上下文中显示
        Toast.makeText(this, resId, duration).show();
    }
}
