#
# Copyright (C) 2022 Sebastiano Barezzi
#
# SPDX-License-Identifier: Apache-2.0
#
"""Android build prop library."""

from __future__ import annotations
from pathlib import Path
from typing import Any, Callable, List, Optional, Union

from sebaubuntu_libs.libcompat.distutils.util import strtobool

class BuildProp(dict):
	"""
	A class representing a build prop.
	This class basically mimics Android props system, with both getprop and setprop commands
	"""
	@classmethod
	def from_file(cls, file: Path):
		"""Create a BuildProp object from a file."""
		build_prop = cls()
		build_prop.import_props(file)
		return build_prop

	def __str__(self):
		return self.get_readable_list()

	def get_readable_list(self, excluded_props: List[str] = []):
		ordered_props = dict(sorted(self.items()))

		for excluded_prop in excluded_props:
			ordered_props.pop(excluded_prop, None)

		return "\n".join(f"{key}={value}" for key, value in ordered_props.items()) + "\n"

	def import_props(self, file: Union[Path, BuildProp]):
		if isinstance(file, BuildProp):
			text = str(file)
		else:
			text = file.read_text(encoding="utf-8")

		for prop in text.splitlines():
			if prop.startswith("#"):
				continue
			try:
				prop_name, prop_value = prop.split("=", 1)
			except ValueError:
				continue
			else:
				self.set_prop(prop_name, prop_value)

	def _get_prop(self, key: str, data_type: Callable[[str], Any] = str, default: Any = None):
		if key in self:
			try:
				return data_type(self[key])
			except ValueError:
				return default
		else:
			return default

	def get_prop(self, key: str, default: Optional[str] = None) -> Optional[str]:
		return self._get_prop(key, str, default)

	def get_prop_bool(self, key: str, default: bool = False) -> bool:
		return self._get_prop(key, lambda x: bool(strtobool(x)), default)

	def get_prop_int(self, key: str, default: int = 0) -> int:
		return self._get_prop(key, int, default)

	def get_prop_float(self, key: str, default: float = 0.0) -> float:
		return self._get_prop(key, float, default)

	def set_prop(self, key: str, value: str):
		assert isinstance(value, str), f"value must be a string, not {type(value)}"
		self[key] = value

	def write_to_file(self, path: Path, excluded_props: List[str] = []):
		path.write_text(self.get_readable_list(excluded_props), encoding="utf-8")
