import base64
import codecs
import hashlib
import mimetypes
import os

from lektor.utils import deprecated


class FileContents:
    @deprecated(name="FileContents", version="3.4.0")
    def __init__(self, filename):
        self.filename = filename
        self._md5 = None
        self._sha1 = None
        self._integrity = None
        self._mimetype = mimetypes.guess_type(filename)[0] or "application/octet-stream"

    @property
    def sha1(self):
        self._ensure_hashes()
        return self._sha1

    @property
    def md5(self):
        self._ensure_hashes()
        return self._md5

    @property
    def integrity(self):
        self._ensure_hashes()
        return self._integrity

    @property
    def mimetype(self):
        return self._mimetype

    @property
    def bytes(self):
        try:
            return os.stat(self.filename).st_size
        except OSError:
            return 0

    def as_data_url(self, mediatype=None):
        if mediatype is None:
            mediatype = self.mimetype
        return f"data:{mediatype};base64,{self.as_base64()}"

    def as_text(self):
        with self.open() as f:
            return f.read()

    def as_bytes(self):
        with self.open("rb") as f:
            return f.read()

    def as_base64(self):
        return base64.b64encode(self.as_bytes())

    def open(self, mode="r", encoding=None):
        if mode == "rb":
            return open(self.filename, "rb")
        if mode != "r":
            raise TypeError("Can only open files for reading")
        # pylint: disable=deprecated-method
        return codecs.open(self.filename, encoding=encoding or "utf-8")

    def _ensure_hashes(self):
        if self._md5 is not None:
            return
        with self.open("rb") as f:
            md5 = hashlib.md5()
            sha1 = hashlib.sha1()
            sha384 = hashlib.sha384()
            while 1:
                chunk = f.read(16384)
                if not chunk:
                    break
                md5.update(chunk)
                sha1.update(chunk)
                sha384.update(chunk)
            self._md5 = md5.hexdigest()
            self._sha1 = sha1.hexdigest()
            self._integrity = "sha384-" + base64.b64encode(sha384.digest()).decode(
                "ascii"
            )

    def __repr__(self):
        return f"<FileContents {self.filename!r} md5={self.md5!r}>"
