# SPDX-FileCopyrightText: 2022 geisserml <geisserml@gmail.com>
# SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause

from pypdfium2._helpers import (
    opener,
    saver,
    toc,
    pdf_renderer,
    page_renderer,
    text_inserter,
    text_extractor,
)
from pypdfium2 import _pypdfium as pdfium


class PdfDocument:
    """
    Document helper class.
    
    Parameters:
        input_obj: The file or data to load.
        password: A password to unlock the PDF, if encrypted.
    """
    
    def __init__(
            self,
            input_obj,
            password = None,
        ):
        self._input_obj = input_obj
        self._password = password
        self._pdf, self._ld_data = opener.open_pdf_auto(
            self._input_obj,
            password = self._password,
        )
    
    def __len__(self):
        """ Get the number of pages the PDF has. """
        return pdfium.FPDF_GetPageCount(self._pdf)
    
    @property
    def raw(self):
        """ Get the raw PDFium ``FPDF_DOCUMENT`` handle. """
        return self._pdf
    
    def close(self):
        """ Close the document to release allocated memory. This method must be called when done with processing the PDF. """
        return opener.close_pdf(self._pdf, self._ld_data)
    
    def save(self, *args, **kws):
        """ Save the PDF into an output byte buffer (see :func:`.save_pdf`). """
        return saver.save_pdf(self._pdf, *args, **kws)
    
    def get_page(self, index):
        """ Get the page at *index* (``FPDF_PAGE``). """
        return opener.open_page(self._pdf, index)
    
    def get_textpage(self, index):
        """ Get the text page at *index* (:class:`.PdfTextPage`). """
        return text_extractor.PdfTextPage(self.get_page(index), close_input=True)
    
    def get_toc(self, **kws):
        """ Incrementally read the document's table of contents (see :func:`.get_toc`). """
        yield from toc.get_toc(self._pdf, **kws)
    
    def render_page_tobytes(self, index, **kws):
        """ Render a single page to bytes (see :func:`.render_page_tobytes`). """
        return page_renderer.render_page_tobytes(self._pdf, page_index=index, **kws)
    
    def render_pdf_tobytes(self, **kws):
        """ Incrementally render multiple pages to bytes (see :func:`.render_pdf_tobytes`). """
        yield from pdf_renderer.render_pdf_tobytes(self._input_obj, password=self._password, **kws)
    
    def render_page_topil(self, index, **kws):
        """ Render a single page to a :mod:`PIL` image (see :func:`.render_page_topil`). """
        return page_renderer.render_page_topil(self._pdf, page_index=index, **kws)
    
    def render_pdf_topil(self, **kws):
        """ Incrementally render multiple pages to :mod:`PIL` images (see :func:`.render_pdf_topil`). """
        yield from pdf_renderer.render_pdf_topil(self._input_obj, password=self._password, **kws)
    
    def insert_text(self, index, **kws):
        """ Insert text into a page (see :func:`.insert_text`). """
        return text_inserter.insert_text(self._pdf, page_index=index, **kws)
