# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/google/GDoc.ipynb.

# %% auto 0
__all__ = ['get_document_by_id', 'GDoc_StyleEnum', 'GDoc_Text_Style', 'GDoc_Element_TextRun', 'GDoc_Element',
           'GDoc_Paragraph_Style', 'GDoc_Paragraph', 'GDoc_SectionBreak_Style', 'GDoc_SectionBreak', 'GDoc_Content',
           'GDoc', 'DocState', 'generate_delete_json', 'generate_insert_json', 'generate_update_style',
           'generate_insert_hyperlink']

# %% ../../nbs/google/GDoc.ipynb 2
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Any, Optional, Callable


import domolibrary_extensions.google.GAuth as ga

# %% ../../nbs/google/GDoc.ipynb 5
def get_document_by_id(service, document_id):
    document = service.documents().get(documentId=document_id).execute()
    return document

# %% ../../nbs/google/GDoc.ipynb 7
class GDoc_StyleEnum(Enum):
    HEADING_1 = "HEADING_1"
    HEADING_2 = "HEADING_2"

# %% ../../nbs/google/GDoc.ipynb 8
@dataclass
class GDoc_Text_Style:
    pass


@dataclass
class GDoc_Element_TextRun:
    content: str

    textStyle: GDoc_Text_Style
    text: str

    @classmethod
    def _from_json(cls, obj):

        return cls(
            content=obj.get("content"),
            textStyle=obj.get("textStyle"),
            text=obj.get("content").strip(),
        )


@dataclass
class GDoc_Element:
    startIndex: int
    endIndex: int
    textRun: GDoc_Element_TextRun

    @classmethod
    def _from_json(cls, obj):
        return GDoc_Element(
            startIndex=obj.get("startIndex"),
            endIndex=obj.get("endIndex"),
            textRun=GDoc_Element_TextRun._from_json(obj.get("textRun")),
        )


@dataclass
class GDoc_Paragraph_Style:

    headingId: Optional[str]

    namedStyleType: str
    direction: str

    @classmethod
    def _from_json(cls, obj):

        return cls(
            headingId=obj.get("headingId"),
            namedStyleType=obj["namedStyleType"],
            direction=obj["direction"],
        )


@dataclass
class GDoc_Paragraph:

    elements: List[GDoc_Element]

    paragraphStyle: Optional[GDoc_Paragraph_Style]

    @classmethod
    def _from_json(cls, obj):

        return cls(
            elements=[
                GDoc_Element._from_json(element) for element in obj.get("elements")
            ],
            paragraphStyle=GDoc_Paragraph_Style._from_json(obj.get("paragraphStyle")),
        )


@dataclass
class GDoc_SectionBreak_Style:

    columnSeparatorStyle: str
    contentDirection: str

    sectionType: str


@dataclass
class GDoc_SectionBreak:

    sectionStyle: GDoc_SectionBreak_Style


@dataclass
class GDoc_Content:

    startIndex: Optional[int]

    endIndex: Optional[int]

    paragraph: Optional[GDoc_Paragraph]

    sectionBreak: Optional[GDoc_SectionBreak]

    @classmethod
    def _from_json(cls, obj):

        gdoc_paragraph = (
            GDoc_Paragraph._from_json(obj.get("paragraph"))
            if obj.get("paragraph")
            else None
        )

        return cls(
            startIndex=obj.get("startIndex"),
            endIndex=obj.get("endIndex"),
            sectionBreak=obj.get("sectionBreak"),
            paragraph=gdoc_paragraph,
        )

# %% ../../nbs/google/GDoc.ipynb 9
@dataclass
class GDoc:
    auth: ga.GoogleAuth = field(repr=False)
    service: Any = field(repr=False)
    document_id: str
    # url: str

    document: Any = field(repr=False)

    gdoc_body: List[GDoc_Content] = field(default=None)

    @classmethod
    def get_by_id(cls, document_id, auth=None, service=None, return_raw: bool = False):
        require_base_url = "https://docs.googleapis.com/"

        if not auth and not service:
            raise ga.GAuth_Required()

        if not service or service._baseUrl != require_base_url:
            if not auth:
                raise ga.GAuth_Required()

            service = auth.generate_service("docs", "v1")

        doc = get_document_by_id(service=service, document_id=document_id)

        gdoc_body = [
            GDoc_Content._from_json(content)
            for content in doc.get("body", {}).get("content")
        ]

        if return_raw:
            return doc

        return cls(
            auth=auth,
            service=service,
            document_id=document_id,
            document=doc,
            gdoc_body=gdoc_body,
        )

# %% ../../nbs/google/GDoc.ipynb 11
@dataclass
class DocState:
    cmds: List[dict] = field(default_factory=lambda: [])
    start_index: int = None
    end_index: int = None
    text: str = None

    function_ls: List[Callable] = field(default_factory=lambda: [])

    def run(self):
        [fn(self) for fn in self.function_ls]

        return self.cmds


def generate_delete_json(
    state: DocState, start_index: int = None, end_index: int = None
):
    start_index = start_index or state.start_index
    end_index = end_index or state.end_index

    state.cmds.append(
        {
            "deleteContentRange": {
                "range": {"startIndex": start_index, "endIndex": end_index}
            }
        }
    )
    state.start_index = start_index
    state.end_index = end_index


def generate_insert_json(
    state: DocState,
    start_index=None,
    text: str = None,
    is_suppress_add_new_line: bool = False,
):
    if not is_suppress_add_new_line and not text.endswith("\n"):
        text += "\n"

    start_index = start_index or state.start_index
    text = text or state.text

    state.cmds.append(
        {
            "insertText": {
                "location": {"index": start_index},
                "text": text,
            }
        }
    )

    state.start_index = start_index
    state.text = text
    state.end_index = len(text)


def generate_update_style(
    state: DocState,
    style_type: GDoc_StyleEnum = None,
    start_index=None,
    text=None,
):
    start_index = start_index or state.start_index
    text = text or state.text
    end_index = len(text) + start_index

    state.cmds.append(
        {
            "updateParagraphStyle": {
                "range": {"startIndex": start_index, "endIndex": end_index},
                "paragraphStyle": {"namedStyleType": style_type.value},
                "fields": "namedStyleType",
            }
        }
    )

    state.start_index = start_index
    state.text = text
    state.end_index = len(text)


def generate_insert_hyperlink(
    state: DocState,
    start_index: int = None,
    text: str = None,
    url: str = None,
):
    start_index = start_index or state.start_index
    text = text or state.text
    end_index = len(text) + start_index
    url = url or state.url

    state.cmds.append(
        {
            "updateTextStyle": {
                "textStyle": {
                    "link": {"url": url}  # Please set the modified URL here.
                },
                "range": {"startIndex": start_index, "endIndex": end_index},
                "fields": "link",
            }
        }
    )

    state.start_index = start_index
    state.text = text
    state.end_index = len(text)
    state.url = url
