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

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.widget.RemoteViews;

import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;

/**
 * 笔记小部件基础提供者抽象类
 * 
 * 功能概述:
 * 1. 管理小部件生命周期
 * 2. 处理小部件点击事件
 * 3. 从数据库加载笔记数据更新小部件视图
 * 4. 支持隐私模式显示
 * 
 * 子类需要实现以下抽象方法：
 * - getBgResourceId()    : 获取背景资源ID
 * - getLayoutId()        : 获取布局资源ID
 * - getWidgetType()      : 获取小部件类型
 */
public abstract class NoteWidgetProvider extends AppWidgetProvider {

    // 数据库查询字段
    private static final String[] PROJECTION = new String[] {
        NoteColumns.ID,
        NoteColumns.BG_COLOR_ID,
        NoteColumns.SNIPPET,
        NoteColumns.WIDGET_ID // 添加字段用于数据一致性检查
    };

    // 查询字段索引
    private static final int COLUMN_ID           = 0;
    private static final int COLUMN_BG_COLOR_ID  = 1;
    private static final int COLUMN_SNIPPET      = 2;
    private static final int COLUMN_WIDGET_ID    = 3; // 添加的索引
    
    private static final String TAG = "NoteWidgetProvider";

    // ========================== 生命周期方法 ==========================
    
    /**
     * 当小部件被删除时调用 - 清理相关笔记的widget_id字段
     * 
     * @param context     应用上下文
     * @param appWidgetIds 被删除的小部件ID数组
     */
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        try {
            // 防止空指针异常
            if (context == null || appWidgetIds == null || appWidgetIds.length == 0) {
                Log.w(TAG, "无效的小部件删除请求");
                return;
            }

            ContentValues values = new ContentValues();
            values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            
            for (int widgetId : appWidgetIds) {
                // 使用try-catch防止个别更新失败中断整个操作
                try {
                    int rowsUpdated = context.getContentResolver().update(
                        Notes.CONTENT_NOTE_URI,
                        values,
                        NoteColumns.WIDGET_ID + "=?",
                        new String[] { String.valueOf(widgetId) }
                    );
                    
                    Log.d(TAG, "已清理小部件 " + widgetId + " 关联的笔记引用，影响行数: " + rowsUpdated);
                } catch (Exception e) {
                    Log.e(TAG, "清理小部件 " + widgetId + " 关联的笔记引用时出错", e);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "小部件删除处理发生未预期错误", e);
        }
    }

    // ========================== 核心功能方法 ==========================
    
    /**
     * 获取与指定小部件关联的笔记信息
     * 
     * @param context  应用上下文
     * @param widgetId 小部件ID
     * @return 笔记数据Cursor（需在调用处关闭）
     */
    protected Cursor getNoteWidgetInfo(Context context, int widgetId) {
        if (context == null || widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
            return null;
        }
        
        String selection = NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?";
        String[] selectionArgs = new String[] { 
            String.valueOf(widgetId), 
            String.valueOf(Notes.ID_TRASH_FOLDER) // 修正: TRASH_FOLER -> TRASH_FOLDER
        };
        
        try {
            return context.getContentResolver().query(
                Notes.CONTENT_NOTE_URI,
                PROJECTION,
                selection,
                selectionArgs,
                null
            );
        } catch (Exception e) {
            Log.e(TAG, "查询小部件 " + widgetId + " 关联笔记信息时出错", e);
            return null;
        }
    }

    /**
     * 更新小部件显示 - 公开方法供外部调用
     * 
     * @param context         应用上下文
     * @param appWidgetManager 小部件管理器
     * @param appWidgetIds     要更新的小部件ID数组
     */
    protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        update(context, appWidgetManager, appWidgetIds, false);
    }

    /**
     * 更新小部件显示（支持隐私模式）- 内部实现
     * 
     * @param context         应用上下文
     * @param appWidgetManager 小部件管理器
     * @param appWidgetIds     要更新的小部件ID数组
     * @param privacyMode     是否为隐私模式（隐藏真实内容）
     */
    private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
            boolean privacyMode) {
            
        if (context == null || appWidgetManager == null || appWidgetIds == null) {
            Log.w(TAG, "无效的更新请求参数");
            return;
        }
        
        for (int widgetId : appWidgetIds) {
            // 跳过无效小部件ID
            if (widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
                continue;
            }

            // 初始化默认值
            int bgId = ResourceParser.NoteColor.YELLOW.id;
            String snippet = "";
            long noteId = Notes.DEFAULT_NOTE_ID;
            
            // 准备笔记编辑意图
            Intent noteIntent = new Intent(context, NoteEditActivity.class);
            noteIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            noteIntent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, widgetId);
            noteIntent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());

            // 查询数据库获取笔记信息
            try (Cursor cursor = getNoteWidgetInfo(context, widgetId)) {
                if (cursor != null && cursor.moveToFirst()) {
                    // 安全检查：确保一个WidgetID只关联一个笔记
                    if (cursor.getCount() > 1) {
                        Log.w(TAG, "小部件 " + widgetId + " 关联多个笔记，请检查数据一致性");
                        
                        // 清除异常关联的笔记
                        cleanInvalidWidgetLinks(context, widgetId, cursor);
                        
                        // 只处理第一条记录
                    }
                    
                    // 获取笔记数据
                    noteId = cursor.getLong(COLUMN_ID);
                    snippet = cursor.getString(COLUMN_SNIPPET);
                    bgId = cursor.getInt(COLUMN_BG_COLOR_ID);
                    
                    noteIntent.putExtra(Intent.EXTRA_UID, noteId);
                    noteIntent.setAction(Intent.ACTION_VIEW);
                    
                    // 检查数据一致性
                    int storedWidgetId = cursor.getInt(COLUMN_WIDGET_ID);
                    if (storedWidgetId != widgetId) {
                        Log.w(TAG, String.format(
                            "笔记%d的小部件ID不一致: 数据库=%d, 请求=%d", 
                            noteId, storedWidgetId, widgetId
                        ));
                    }
                } else {
                    // 未找到关联笔记
                    snippet = context.getString(R.string.widget_no_content);
                    noteIntent.setAction(Intent.ACTION_INSERT_OR_EDIT);
                }
            } catch (Exception e) {
                Log.e(TAG, "处理小部件 " + widgetId + " 时发生错误", e);
                snippet = context.getString(R.string.widget_error_loading);
            }

            // 创建小部件视图
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), getLayoutId());
            
            // 设置背景
            int bgResId = getBgResourceId(bgId);
            remoteViews.setImageViewResource(R.id.widget_bg_image, bgResId);
            noteIntent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
            
            // 创建点击意图
            PendingIntent pendingIntent;
            if (privacyMode) {
                // 隐私模式：显示提示文本，点击进入主列表
                remoteViews.setTextViewText(R.id.widget_text, 
                    context.getString(R.string.widget_privacy_mode));
                
                Intent listIntent = new Intent(context, NotesListActivity.class);
                pendingIntent = PendingIntent.getActivity(
                    context, widgetId, listIntent, 
                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
                );
            } else {
                // 正常模式：显示笔记摘要，点击进入笔记编辑
                remoteViews.setTextViewText(R.id.widget_text, snippet);
                
                pendingIntent = PendingIntent.getActivity(
                    context, widgetId, noteIntent, 
                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
                );
            }
            
            // 设置点击事件
            remoteViews.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
            
            // 应用更新
            try {
                appWidgetManager.updateAppWidget(widgetId, remoteViews);
                Log.d(TAG, "成功更新小部件: " + widgetId);
            } catch (Exception e) {
                Log.e(TAG, "更新小部件 " + widgetId + " 失败", e);
            }
        }
    }

    // ========================== 抽象方法 ==========================
    
    /**
     * 获取背景资源ID
     * 
     * @param bgId 背景颜色ID
     * @return 对应的drawable资源ID
     */
    protected abstract int getBgResourceId(int bgId);

    /**
     * 获取小部件布局资源ID
     * 
     * @return 布局资源ID
     */
    protected abstract int getLayoutId();

    /**
     * 获取小部件类型
     * 
     * @return 小部件类型常量
     */
    protected abstract int getWidgetType();
    
    // ========================== 新增功能方法 ==========================
    
    /**
     * 清理无效的小部件关联（数据一致性修复）
     * 
     * @param context 应用上下文
     * @param widgetId 小部件ID
     * @param cursor 查询到的关联笔记数据
     */
    private void cleanInvalidWidgetLinks(Context context, int widgetId, Cursor cursor) {
        if (cursor == null) return;
        
        ContentValues values = new ContentValues();
        values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
        
        try {
            // 遍历所有关联笔记
            cursor.moveToPosition(-1); // 移动到开始位置
            while (cursor.moveToNext()) {
                long currentNoteId = cursor.getLong(COLUMN_ID);
                int currentWidgetId = cursor.getInt(COLUMN_WIDGET_ID);
                
                // 只保留最新关联的笔记
                if (currentWidgetId == widgetId) {
                    Log.i(TAG, "保留笔记 " + currentNoteId + " 关联的小部件 " + widgetId);
                    continue;
                }
                
                // 解除其他笔记的关联
                Uri noteUri = ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, currentNoteId);
                int rows = context.getContentResolver().update(
                    noteUri, values, null, null);
                
                if (rows > 0) {
                    Log.w(TAG, "已清理笔记 " + currentNoteId + " 上的小部件关联");
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "清理无效小部件关联时出错", e);
        }
    }
    
    // ========================== 新增功能：定时刷新支持 ==========================
    
    /**
     * 设置小部件自动刷新间隔
     * 
     * @param context 应用上下文
     * @param appWidgetId 小部件ID
     * @param intervalMinutes 刷新间隔（分钟）
     */
    public static void setUpdateInterval(Context context, int appWidgetId, int intervalMinutes) {
        // 最小间隔限制
        if (intervalMinutes < 15) {
            Log.w(TAG, "刷新间隔不能小于15分钟");
            intervalMinutes = 60; // 默认1小时
        }
        
        // TODO: 实现AlarmManager定时刷新逻辑
    }
    
    // ========================== 新增功能：多尺寸小部件支持 ==========================
    
    /**
     * 小部件尺寸类型
     */
    public enum WidgetSize {
        SIZE_1X1,
        SIZE_2X1,
        SIZE_2X2,
        SIZE_3X3
    }
    
    /**
     * 获取当前小部件尺寸
     * 
     * @param context 应用上下文
     * @param appWidgetId 小部件ID
     * @return 小部件尺寸类型
     */
    protected WidgetSize getWidgetSize(Context context, int appWidgetId) {
        // TODO: 实现小部件尺寸检测逻辑
        return WidgetSize.SIZE_2X1; // 默认返回2x1
    }
}