/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

// 声明该类所在的包名，表明这个类属于 `com.yami.shop.bean` 包，在Java项目中，包用于对类进行分类组织，方便代码管理和避免类名冲突等情况。
package com.yami.shop.bean;

import java.util.ArrayList;
import java.util.List;

// 导入 `SmsInfoBo` 类，从类名推测它是与短信信息相关的业务对象（Business Object），这个类应该包含了短信相关的各种属性以及对应的业务逻辑所需要的数据结构，会在本类中用于存储和操作短信相关的信息。
import com.yami.shop.bean.bo.SmsInfoBo;
// 导入 `hutool` 工具库中用于集合操作的工具类 `CollectionUtil`，它提供了许多便捷的方法来处理集合相关的常见操作，例如判断集合是否为空、对集合进行合并、拆分等操作，在这里主要用于判断短信信息列表是否为空的情况。
import cn.hutool.core.collection.CollectionUtil;

/**
 * @author lanhai
 * 这个类 `SmsInfoContext` 的作用是作为短信信息的上下文管理类，它利用 `ThreadLocal` 机制来实现在多线程环境下，每个线程都能独立地管理自己的短信信息集合（以 `SmsInfoBo` 列表形式存储），
 * 提供了获取、设置、添加以及清理短信信息的相关方法，方便在不同的业务逻辑中对当前线程的短信信息进行操作，避免了多线程之间短信信息数据的相互干扰。
 */
public class SmsInfoContext {

	/**
	 * The request holder.
	 * 定义一个静态的 `ThreadLocal` 变量 `smsInfoHolder`，用于在每个线程中存储短信信息列表（类型为 `List<SmsInfoBo>`）。
	 * `ThreadLocal` 的作用是让每个线程都有自己独立的变量副本，也就是说，不同线程通过这个 `smsInfoHolder` 访问到的短信信息列表是相互独立的，互不影响，
	 * 这样就可以在多线程的场景下安全地处理各自线程相关的短信业务数据。
	 */
	private static ThreadLocal<List<SmsInfoBo>> smsInfoHolder = new ThreadLocal<List<SmsInfoBo>>();

	/**
	 * 获取当前线程中存储的短信信息列表。
	 * 首先通过 `smsInfoHolder.get()` 方法尝试获取当前线程对应的短信信息列表，然后使用 `CollectionUtil.isEmpty(list)` 判断获取到的列表是否为空。
	 * 如果为空（意味着当前线程还没有设置过短信信息列表或者之前设置的列表被清理了等情况），则返回一个新创建的空的 `ArrayList`，这样调用这个方法的地方可以放心地使用返回的列表进行后续操作，不用担心出现空指针异常等问题。
	 * 如果获取到的列表不为空，则直接返回当前线程通过 `smsInfoHolder` 存储的短信信息列表，以便后续对已有的短信信息进行操作，比如遍历、修改等。
	 *
	 * @return 当前线程中存储的短信信息列表，如果当前线程原本没有设置过短信信息列表，则返回一个新的空列表。
	 */
	public static List<SmsInfoBo> get() {
		List<SmsInfoBo> list = smsInfoHolder.get();
		if (CollectionUtil.isEmpty(list)) {
			return new ArrayList<>();
		}
		return smsInfoHolder.get();
	}

	/**
	 * 设置当前线程中存储的短信信息列表。
	 * 该方法接收一个 `List<SmsInfoBo>` 类型的参数 `smsInfoBos`，然后通过 `smsInfoHolder.set(smsInfoBos)` 将这个参数对应的短信信息列表设置到当前线程的 `ThreadLocal` 变量中，
	 * 这样在当前线程后续的其他代码中通过 `get` 方法获取到的就是新设置的这个短信信息列表了，方便在不同的业务逻辑阶段更新当前线程所使用的短信信息数据。
	 *
	 * @param smsInfoBos 要设置到当前线程的短信信息列表。
	 */
	public static void set(List<SmsInfoBo> smsInfoBos) {
		smsInfoHolder.set(smsInfoBos);
	}

	/**
	 * 向当前线程中存储的短信信息列表中添加一条短信信息（`SmsInfoBo` 对象）。
	 * 首先通过 `smsInfoHolder.get()` 获取当前线程已有的短信信息列表，接着使用 `CollectionUtil.isEmpty(smsInfoBos)` 判断这个列表是否为空。
	 * 如果为空，说明当前线程还没有短信信息列表，那么就创建一个新的空的 `ArrayList` 作为初始的短信信息列表。然后将传入的短信信息对象 `smsInfoBo` 添加到这个列表中，
	 * 最后再通过 `smsInfoHolder.set(smsInfoBos)` 将更新后的包含了新添加短信信息的列表重新设置回当前线程的 `ThreadLocal` 变量中，确保线程中存储的短信信息列表始终是最新的状态，方便后续继续操作。
	 *
	 * @param smsInfoBo 要添加到当前线程短信信息列表中的短信信息对象。
	 */
	public static void put(SmsInfoBo smsInfoBo) {
		List<SmsInfoBo> smsInfoBos = smsInfoHolder.get();
		if (CollectionUtil.isEmpty(smsInfoBos)) {
			smsInfoBos = new ArrayList<>();
		}
		smsInfoBos.add(smsInfoBo);
		smsInfoHolder.set(smsInfoBos);
	}

	/**
	 * 清理当前线程中存储的短信信息列表。
	 * 首先通过 `smsInfoHolder.get()` 获取当前线程中存储的短信信息列表，判断其是否不为 `null`，如果不为 `null`，则调用 `smsInfoHolder.remove()` 方法将当前线程对应的短信信息列表从 `ThreadLocal` 变量中移除，
	 * 这样当前线程后续再通过 `get` 等方法获取短信信息列表时，得到的就是初始的默认状态（比如为空的情况）。这个方法常用于在某个业务逻辑执行完毕后，清理当前线程相关的短信信息数据，防止数据残留导致的内存占用以及可能出现的数据混乱等问题。
	 */
	public static void clean() {
		if (smsInfoHolder.get()!= null) {
			smsInfoHolder.remove();
		}
	}
}