from collections.abc import Iterable

import anyio
import click
from tqdm.asyncio import tqdm

from albi0.container import ProcessorContainer
from albi0.typing import DownloadPostProcessMethod

from .downloader import Downloader, DownloadParams
from .version import AbstractVersionManager

updaters: ProcessorContainer['Updater'] = ProcessorContainer()


class Updater:
	def __init__(
		self,
		name: str,
		desc: str,
		*,
		version_manager: AbstractVersionManager,
		downloader: Downloader,
		postprocess_handler: DownloadPostProcessMethod | None = None,
	) -> None:
		self.name = name
		self.desc = desc
		self.version_manager = version_manager
		self.downloader = downloader
		self.postprocess_handler = postprocess_handler

		updaters[self.name] = self

	def _log_message(self, message: str) -> None:
		click.echo(f'更新器|[{self.name}]: {message}')

	async def update(
		self,
		*,
		progress_bar: tqdm | None = None,
		save_manifest: bool = True,
		patterns: Iterable[str] = (),
		semaphore: anyio.Semaphore | None = None,
	) -> None:
		"""异步更新资源文件

		检查版本是否过期，如果需要更新则下载新的资源文件并保存清单，过滤后没有需要更新的文件时不会保存清单。

		Args:
			progress_bar: 进度条
			semaphore: 并发限制
			save_manifest: 是否保存清单
			patterns: glob语法的文件名过滤模式，用于过滤希望检查更新的文件，
			如果为空则检查所有文件。
		"""
		manifest = self.version_manager.generate_update_manifest(*patterns)
		if not manifest:
			self._log_message('没有需要更新的文件，运行结束')
			return

		items = manifest.items
		self._log_message(f'需要更新的文件数量: {len(items)}')
		tasks = [
			DownloadParams(url=item.remote_filename, filename=local_fn)
			for local_fn, item in items.items()
		]
		if tasks:
			await self.downloader.downloads(
				*tasks,
				progress_bar=progress_bar,
				postprocess_handler=self.postprocess_handler,
				semaphore=semaphore,
			)

		if not tasks:
			self._log_message('没有需要更新的文件，不保存资源清单')
			return

		if not save_manifest:
			self._log_message('参数save_manifest为False，不保存资源清单')
			return

		self.version_manager.save_manifest_to_local(manifest)
		self._log_message('资源清单更新完成')
