# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/03_bytes copy.ipynb.

# %% auto 0
__all__ = ['Bytes']

# %% ../nbs/03_bytes copy.ipynb 5
import os
from numbers import Number
from dataclasses import dataclass, field
from typing import Union, Optional

# %% ../nbs/03_bytes copy.ipynb 7
from .enums import (ByteUnit)

# %% ../nbs/03_bytes copy.ipynb 9
@dataclass
class Bytes:
    """A class for representing sizes in various byte units."""
    size: int = field(default=0, repr=False)
    precision: Optional[int] = field(default=3, repr=False)
    
    @classmethod
    def to(cls, num: Number, precision: Optional[int] = None) -> 'Bytes':
        return cls(size=num, precision=(precision or cls.precision))

    def __repr__(self) -> str:
        return ByteUnit.format(self.size, precision=self.precision)
    
    def __add__(self, other: Union['Bytes', int]):
        """Add two Bytes instances or a Bytes instance and a byte count.
        
        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        Bytes
            The Bytes instance representing the total size.
        """
        if isinstance(other, Bytes):
            total_bytes = self.size + other.size
        else:
            total_bytes = self.size + other
        return Bytes(total_bytes, precision=self.precision)

    def __sub__(self, other: Union['Bytes', int]):
        """Subtract a Bytes instance or a byte count from this Bytes instance.
        
        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        Bytes
            The Bytes instance representing the remaining size.
        """
        if isinstance(other, Bytes):
            total_bytes = self.size - other.size
        else:
            total_bytes = self.size - other
        if total_bytes < 0: total_bytes = 0
        return Bytes(total_bytes, precision=self.precision)
    
    def __mul__(self, other: Union['Bytes', int]):
        """Multiply this Bytes instance by a Bytes instance or a byte count.
        
        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        Bytes
            The Bytes instance representing the total size.
        """
        if isinstance(other, Bytes):
            total_bytes = self.size * other.size
        else:
            total_bytes = self.size * other
        return Bytes(total_bytes, precision=self.precision)

    def __truediv__(self, other: Union['Bytes', int]):
        """Divide this Bytes instance by a Bytes instance or a byte count.
        
        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        Bytes
            The Bytes instance representing the total size.
        """
        if isinstance(other, Bytes):
            total_bytes = self.size / other.size
        else:
            total_bytes = self.size / other
        return Bytes(total_bytes, precision=self.decimals)

    @staticmethod
    def from_file(file_path: str, precision: Optional[int] = 2) -> 'Bytes':
        """Create a Bytes instance representing the size of a file.
        
        Parameters
        ----------
        file_path : str
            The path to the file.
        decimals : int, optional
            The number of decimal places to precision to (default is 2).

        Returns
        -------
        Bytes
            The Bytes instance representing the size of the file.
        """
        size = os.path.getsize(file_path)
        return Bytes(size, precision=precision)

    @staticmethod
    def from_dir(dir_path: str, precision: Optional[int] = 2) -> 'Bytes':
        """Create a Bytes instance representing the total size of a directory.
        
        Parameters
        ----------
        dir_path : str
            The path to the directory.
        decimals : int, optional
            The number of decimal places to precision to (default is 2).

        Returns
        -------
        Bytes
            The Bytes instance representing the total size of the directory.
        """
        total = 0
        for dirpath, dirnames, filenames in os.walk(dir_path):
            for f in filenames:
                fp = os.path.join(dirpath, f)
                if not os.path.islink(fp):
                    total += os.path.getsize(fp)
        return Bytes(total, precision=precision)
    
    def to_bytes(self) -> int:
        """Convert the Bytes instance to a byte count.

        Returns
        -------
        int
            The byte count.
        """
        return self.size
    

    def __lt__(self, other: Union['Bytes', int]) -> bool:
        """Less than comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is less than the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size < other.size
        else:
            return self.size < other

    def __le__(self, other: Union['Bytes', int]) -> bool:
        """Less than or equal to comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is less than or equal to the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size <= other.size
        else:
            return self.size <= other

    def __gt__(self, other: Union['Bytes', int]) -> bool:
        """Greater than comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is greater than the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size > other.size
        else:
            return self.size > other

    def __ge__(self, other: Union['Bytes', int]) -> bool:
        """Greater than or equal to comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is greater than or equal to the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size >= other.size
        else:
            return self.size >= other

    def __eq__(self, other: Union['Bytes', int]) -> bool:
        """Equality comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is equal to the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size == other.size
        else:
            return self.size == other

    def __ne__(self, other: Union['Bytes', int]) -> bool:
        """Not equal to comparison between two Bytes instances or a Bytes instance and a byte count.

        Parameters
        ----------
        other : Bytes or int
            The other Bytes instance or byte count.

        Returns
        -------
        bool
            True if this Bytes instance is not equal to the other, False otherwise.
        """
        if isinstance(other, Bytes):
            return self.size != other.size
        else:
            return self.size != other
