/*
 * 版权所有 (c) 2010-2011，MiCode 开源社区 (www.micode.net)
 * 根据 Apache 许可证 2.0 版本（"许可证"）授权；
 * 除非符合许可证的规定，否则不得使用本文件。
 * 您可以从以下网址获取许可证副本：
 * http://www.apache.org/licenses/LICENSE-2.0
 * 除非适用法律要求或书面同意，本软件按"原样"分发，
 * 没有任何明示或暗示的保证或条件。
 * 详见许可证中规定的权限和限制。
 * （注：这是一份标准的Apache许可证2.0版本的开源声明）
 */

// 声明当前Java文件的包路径（表明该类所在的位置）
package net.micode.notes.ui;

// 导入Android相关的Context类（用于访问应用资源和系统服务）
import android.content.Context;
// 导入Cursor类（用于数据库查询结果的遍历）
import android.database.Cursor;
// 导入Android日志工具类
import android.util.Log;
// 导入Android基础视图类
import android.view.View;
// 导入视图组类（用于视图的容器管理）
import android.view.ViewGroup;
// 导入CursorAdapter类（用于将Cursor数据适配到ListView等控件）
import android.widget.CursorAdapter;

// 导入当前应用的数据模型包
import net.micode.notes.data.Notes;

// 导入Java集合框架相关类
import java.util.Collection;   // 集合框架的根接口
import java.util.HashMap;      // 哈希映射表实现
import java.util.HashSet;      // 哈希集合实现
import java.util.Iterator;     // 迭代器接口

/**
 * 笔记列表适配器
 * 功能：
 * 1. 管理笔记列表数据显示
 * 2. 处理多选模式逻辑
 * 3. 跟踪选中状态
 */
public class NotesListAdapter extends CursorAdapter {
    private static final String TAG = "NotesListAdapter"; // 日志标签
    private final Context mContext; // 上下文对象
    private final HashMap<Integer, Boolean> mSelectedIndex; // 存储选中状态的映射表（位置 -> 是否选中）
    private int mNotesCount; // 笔记总数（不含文件夹）
    private boolean mChoiceMode; // 是否处于多选模式

    /**
     * 小部件属性封装类
     */
    public static class AppWidgetAttribute {
        public int widgetId;    // 小部件ID
        public final ThreadLocal<Integer> widgetType = new ThreadLocal<>() {
            @Override
            protected Integer initialValue() {
                return 0;
            }
        };  // 小部件类型
    }

    /**
     * 构造函数
     * @param context 上下文环境
     */
    public NotesListAdapter(Context context) {
        super(context, null); // 初始化CursorAdapter，初始cursor为null
        mSelectedIndex = new HashMap<>(); // 初始化选中状态集合
        mContext = context; // 保存上下文引用
        mNotesCount = 0; // 初始化笔记数量
    }

    /**
     * 创建新列表项视图
     * @param context 上下文
     * @param cursor 数据游标
     * @param parent 父视图
     * @return 新建的NotesListItem视图
     */
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return new NotesListItem(context); // 创建新的笔记列表项
    }

    /**
     * 绑定数据到列表项视图
     * @param view 要绑定的视图
     * @param context 上下文
     * @param cursor 数据游标
     */
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        if (view instanceof NotesListItem) {
            // 创建笔记数据对象
            NoteItemData itemData = new NoteItemData(context, cursor);
            // 绑定数据到列表项视图
            ((NotesListItem) view).bind(context, itemData, mChoiceMode,
                    isSelectedItem(cursor.getPosition()));
        }
    }

    /**
     * 设置指定位置的选中状态
     * @param position 列表位置
     * @param checked 是否选中
     */
    public void setCheckedItem(final int position, final boolean checked) {
        mSelectedIndex.put(position,  checked); // 更新选中状态
        notifyDataSetChanged(); // 通知视图更新
    }

    /**
     * 检查是否处于多选模式
     * @return true表示正在多选模式
     */
    public boolean isInChoiceMode() {
        return mChoiceMode;
    }

    /**
     * 设置多选模式状态
     * @param mode true进入多选模式，false退出
     */
    public void setChoiceMode(boolean mode) {
        mSelectedIndex.clear();  // 清除所有选中状态
        mChoiceMode = mode; // 更新模式状态
    }

    /**
     * 全选/取消全选所有笔记项
     * @param checked true全选，false取消全选
     */
    public void selectAll(boolean checked) {
        Cursor cursor = getCursor();
        // 遍历所有项
        for (int i = 0; i < getCount(); i++) {
            if (cursor.moveToPosition(i))  {
                // 只处理笔记类型（不包含文件夹）
                if (NoteItemData.getNoteType(cursor)  == Notes.TYPE_NOTE) {
                    setCheckedItem(i, checked); // 设置选中状态
                }
            }
        }
    }

    /**
     * 获取所有选中项的ID集合
     * @return 选中项的ID集合
     */
    public HashSet<Long> getSelectedItemIds() {
        HashSet<Long> itemSet = new HashSet<>();
        // 遍历所有选中项
        for (Integer position : mSelectedIndex.keySet())  {
            if (Boolean.TRUE.equals(mSelectedIndex.get(position))) {
                long id = getItemId(position); // 获取项ID
                // 检查是否为根文件夹（不应该被选中）
                if (id == Notes.ID_ROOT_FOLDER) {
                    Log.d(TAG, "Wrong item id, should not happen");
                } else {
                    itemSet.add(id);  // 添加到结果集
                }
            }
        }
        return itemSet;
    }

    /**
     * 获取选中项关联的小部件属性集合
     * @return 小部件属性集合，可能为null
     */
    public HashSet<AppWidgetAttribute> getSelectedWidget() {
        HashSet<AppWidgetAttribute> itemSet = new HashSet<>();
        // 遍历所有选中项
        for (Integer position : mSelectedIndex.keySet())  {
            if (Boolean.TRUE.equals(mSelectedIndex.get(position))) {
                Cursor c = (Cursor) getItem(position); // 获取项数据
                if (c != null) {
                    AppWidgetAttribute widget = new AppWidgetAttribute();
                    NoteItemData item = new NoteItemData(mContext, c);
                    widget.widgetId  = item.getWidgetId();  // 设置小部件ID
                    widget.widgetType.set(item.getWidgetType());  // 设置小部件类型
                    itemSet.add(widget);  // 添加到结果集
                    /*
                     * 注意：不要在此处关闭cursor，只有适配器可以关闭它
                     */
                } else {
                    Log.e(TAG, "Invalid cursor");
                    return null; // 遇到错误返回null
                }
            }
        }
        return itemSet;
    }

    /**
     * 获取当前选中项数量
     * @return 选中项计数
     */
    public int getSelectedCount() {
        Collection<Boolean> values = mSelectedIndex.values();
        Iterator<Boolean> iter = values.iterator();
        int count = 0;
        // 统计选中状态为true的数量
        while (iter.hasNext())  {
            if (iter.next())  {
                count++;
            }
        }
        return count;
    }

    /**
     * 检查是否所有项都被选中
     * @return true表示全部选中
     */
    public boolean isAllSelected() {
        int checkedCount = getSelectedCount();
        // 选中数量不为0且等于总笔记数量
        return (checkedCount != 0 && checkedCount == mNotesCount);
    }

    /**
     * 检查指定位置是否被选中
     * @param position 要检查的位置
     * @return true表示该位置被选中
     */
    public boolean isSelectedItem(final int position) {
        if (null == mSelectedIndex.get(position))  {
            return false; // 未记录的位置默认为未选中
        }
        return Boolean.TRUE.equals(mSelectedIndex.get(position));
    }

    /**
     * 当内容变化时的回调
     * 重新计算笔记数量
     */
    @Override
    protected void onContentChanged() {
        super.onContentChanged();
        calcNotesCount(); // 更新笔记计数
    }

    /**
     * 切换游标时的回调
     * @param cursor 新游标
     */
    @Override
    public void changeCursor(Cursor cursor) {
        super.changeCursor(cursor);
        calcNotesCount(); // 更新笔记计数
    }

    /**
     * 计算笔记数量（不包括文件夹）
     */
    private void calcNotesCount() {
        mNotesCount = 0;
        // 遍历所有项
        for (int i = 0; i < getCount(); i++) {
            Cursor c = (Cursor) getItem(i);
            if (c != null) {
                // 只统计笔记类型（TYPE_NOTE）
                if (NoteItemData.getNoteType(c)  == Notes.TYPE_NOTE) {
                    mNotesCount++; // 计数增加
                }
            } else {
                Log.e(TAG, "Invalid cursor");
                return; // 遇到错误提前退出
            }
        }
    }
}
