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

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;

// GTaskSyncService类继承自Service，用于管理与Google Tasks的同步相关操作，包括启动同步、取消同步以及广播同步状态等功能
public class GTaskSyncService extends Service {

    // 用于在Intent中传递同步操作类型的字符串常量，作为键来标识具体的操作类型信息
    public final static String ACTION_STRING_NAME = "sync_action_type";

    // 表示启动同步操作的整数值常量，用于在根据操作类型进行判断时识别启动同步的意图
    public final static int ACTION_START_SYNC = 0;

    // 表示取消同步操作的整数值常量，用于在根据操作类型进行判断时识别取消同步的意图
    public final static int ACTION_CANCEL_SYNC = 1;

    // 表示无效操作类型的整数值常量，当获取到的操作类型不匹配已知的有效类型时使用该值来标识
    public final static int ACTION_INVALID = 2;

    // 用于广播同步服务相关状态信息的Intent的动作名称，其他组件可以通过注册监听该动作来接收同步服务的广播消息
    public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service";

    // 在广播Intent中用于传递是否正在同步状态的键名，对应的值为布尔类型，表示同步操作是否正在进行
    public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";

    // 在广播Intent中用于传递同步进度消息的键名，对应的值为字符串类型，可用于展示同步操作的进度相关文本信息
    public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";

    // 静态变量，用于存储正在执行的同步任务对象（GTaskASyncTask类型），方便在不同方法中对同步任务进行控制和判断状态
    private static GTaskASyncTask mSyncTask = null;

    // 静态变量，用于存储同步进度相关的消息字符串，可通过广播传递给其他关注同步进度的组件
    private static String mSyncProgress = "";

    // 启动同步的私有方法，用于创建并执行同步任务
    private void startSync() {
        // 如果当前没有正在执行的同步任务（mSyncTask为null）
        if (mSyncTask == null) {
            // 创建一个新的GTaskASyncTask对象，传入当前服务上下文（this）以及一个完成监听器（OnCompleteListener）
            mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
                // 当同步任务完成时会调用的回调方法
                public void onComplete() {
                    // 将正在执行的同步任务对象置为null，表示同步已结束
                    mSyncTask = null;
                    // 发送一个空消息的广播（可能用于通知其他组件同步已完成等状态变化）
                    sendBroadcast("");
                    // 停止当前服务（因为同步任务已完成，服务的主要工作完成，可以停止自身运行）
                    stopSelf();
                }
            });
            // 发送一个空消息的广播（可能在创建任务后就先通知其他组件同步即将开始等情况）
            sendBroadcast("");
            // 执行同步任务，开始真正的同步操作流程
            mSyncTask.execute();
        }
    }

    // 取消同步的私有方法，用于取消正在执行的同步任务（如果存在的话）
    private void cancelSync() {
        if (mSyncTask != null) {
            mSyncTask.cancelSync();
        }
    }

    // 服务创建时调用的方法，在这里将正在执行的同步任务对象初始化为null，确保服务启动时处于初始状态
    @Override
    public void onCreate() {
        mSyncTask = null;
    }

    // 当服务通过startService()方法启动时会调用此方法，用于处理传入的Intent并根据不同的操作意图执行相应操作
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 从传入的Intent中获取附加的Bundle数据（通常用于传递额外的参数信息）
        Bundle bundle = intent.getExtras();
        // 如果获取到的Bundle不为null且包含表示操作类型的键（ACTION_STRING_NAME）
        if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
            // 根据操作类型的值进行不同的操作分支判断
            switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
                // 如果操作类型是启动同步（ACTION_START_SYNC）
                case ACTION_START_SYNC:
                    startSync();
                    break;
                // 如果操作类型是取消同步（ACTION_CANCEL_SYNC）
                case ACTION_CANCEL_SYNC:
                    cancelSync();
                    break;
                // 其他未知或不处理的操作类型，直接跳过不做操作
                default:
                    break;
            }
            // 返回START_STICKY表示服务在被系统意外终止后会尝试重新创建并保持启动状态（常用于需要持续运行的服务场景）
            return START_STICKY;
        }
        // 如果不符合上述条件或者操作类型无效等情况，调用父类的onStartCommand方法进行默认处理
        return super.onStartCommand(intent, flags, startId);
    }

    // 当系统内存不足时会调用此方法，在这里用于取消正在执行的同步任务（如果存在的话），释放内存资源
    @Override
    public void onLowMemory() {
        if (mSyncTask != null) {
            mSyncTask.cancelSync();
        }
    }

    // 用于服务绑定操作的方法，这里返回null表示不支持绑定操作（如果需要支持绑定，需要返回一个有效的IBinder对象）
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    // 发送广播的公共方法，用于向其他组件广播同步服务的相关状态信息，包括同步进度消息、是否正在同步等
    public void sendBroadcast(String msg) {
        mSyncProgress = msg;
        Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
        intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null);
        intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
        sendBroadcast(intent);
    }

    // 静态公共方法，用于在外部（比如Activity中）启动同步服务进行同步操作，需要传入对应的Activity作为上下文来启动服务
    public static void startSync(Activity activity) {
        // 设置GTaskManager的Activity上下文（可能用于获取相关授权等操作，与同步操作相关联）
        GTaskManager.getInstance().setActivityContext(activity);
        Intent intent = new Intent(activity, GTaskSyncService.class);
        intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);
        activity.startService(intent);
    }

    // 静态公共方法，用于在外部（比如其他组件中）取消正在进行的同步操作，需要传入上下文（Context）来启动服务发送取消同步的意图
    public static void cancelSync(Context context) {
        Intent intent = new Intent(context, GTaskSyncService.class);
        intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
        context.startService(intent);
    }

    // 静态公共方法，用于判断当前是否正在进行同步操作，通过检查正在执行的同步任务对象是否为null来返回相应的布尔值结果
    public static boolean isSyncing() {
        return mSyncTask != null;
    }

    // 静态公共方法，用于获取当前的同步进度相关的字符串消息，返回存储同步进度消息的静态变量的值
    public static String getProgressString() {
        return mSyncProgress;
    }
}