from .service import get_service
from googleapiclient.errors import HttpError
from typing import Literal, Optional

def create_presentation(title: str)->dict:
    """
    To create the empty presentation in the Google Slides.

    Args:
        title (str): The title of the presentation.

    Returns:
        dict: The confirmation of the creation and presentation ID.
    
    Example:
        ```python
        def test_create_presentation():
            try:
                title= 'Testing'
                pptx_creation = create_presentation(
                    title= title,
                )
                return f'Test case passed: {pptx_creation}'
            except Exception as e:
                return f'Error creating presentation: {e}'
        ```
    """
    try:
        service= get_service('slides')
        presentation = service.presentations().create(body= {"title": title}).execute()
        return {
            'message': 'Presentation created Successfully.',
            'presentationId': presentation.get('presentationId')
        }
    except HttpError as error:
        raise Exception(f" Error {error}")

def create_slide(presentation_id: str, slide_id: str, slide_position: int,
                 slide_type: Literal['BLANK', 'TITLE', 'TITLE_AND_BODY', 'TITLE_ONLY', 'SECTION_HEADER', 'ONE_COLUMN_TEXT'])->dict:
    """
    Create a slide in the presentation with specific slide ID.

    The same Slide ID might be useful in inserting the text in that slide.

    Args:
        presentation_id (str): The presentation ID where the slide will be created.
        slide_id (str): The slide ID.
        slide_position (int): The position of the slide in the presentation remember not to give the number greater than slides present.
        slide_type (str): The type of slide if you want to choose a predefined Layout.

            It takes following values:

            - BLANK: Blank layout, with no placeholders.
            - TITLE: Layout with a title and a subtitle.
            - TITLE_AND_BODY: Layout with a title and body.
            - TITLE_ONLY: Layout with only a title.
            - SECTION_HEADER: Layout with a section title.
            - ONE_COLUMN_TEXT: Layout with one title and one body, arranged in a single column.

    Returns:
        dict: The confirmation of the creation and presentation ID.
    
    Example:
        ```python
        def test_create_slide():
            try:
                slide_creation = create_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_5',
                    slide_position= 5,
                    slide_type= 'ONE_COLUMN_TEXT'
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error creating slide: {e}'
        ```
    """
    try:
        service= get_service('slides')
        requests= [
            {
                "createSlide":{
                    "objectId": slide_id,
                    "insertionIndex": slide_position - 1,
                    "slideLayoutReference": {"predefinedLayout": slide_type}
                }
            }
        ]
        response= service.presentations().batchUpdate(
            presentationId= presentation_id,
            body= {"requests": requests}
        ).execute()
        return {
            'message': 'Slide created Successfully.',
            'slideId': response
        }
    except HttpError as error:
        raise Exception(f" Error {error}")

def get_presentation(presentation_id: str) -> dict:
    """
    To get the presentation with the presentation ID.

    Args:
        presentation_id (str): ID of the presentatiton.
    
    Example:
        ```python
        def test_get_presentation():
            try:
                presentation = get_presentation(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw')
                return f'Test case passed: {presentation}'
            except Exception as e:
                return f'Error getting presentation: {e}'
        ```
    """
    try:
        service= get_service('slides')
        response= service.presentations().get(presentationId= presentation_id).execute()
        return {
            'message': 'Presentation retrieved Successfully.',
            'presentation_data': response
        }
    except HttpError as error:
        raise Exception(f" Error {error}")

def add_content_in_blank_slide(presentation_id: str, slide_id: str, slide_title: Optional[str]= '', slide_text: Optional[str]= '')->dict:
    """
    Use this if you have created a BLANK Slide.

    To add content to the specific slide of a specific presentation.
    So basically to add the content in the specific slide you have pass the presentation ID that you received
    when you created the presentation, slideID that you received when you created the slide.
    And we can not simply add the text; We have to create the shape first so every shape will have an ID.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID where the content will be added.
        slide_title (str): The title of the content in the slide. It is optional parameter as slides having no title box will not receive title text.
        slide_text (str): The text of the content in the slide. It is also a optional parameter as slides having only title will not have body.

    Returns:
        str: The presentation ID.
    """
    try:
        title_shape_id= 'title_box'
        content_shape_id= 'text_box'
        service= get_service('slides')
        shapes_creation_requests = [
            {
                "createShape": {
                    "objectId": title_shape_id,
                    "shapeType": "TEXT_BOX",
                    "elementProperties": {
                        "pageObjectId": slide_id,
                        "size": {"height": {"magnitude": 100, "unit": "PT"},
                                 "width": {"magnitude": 500, "unit": "PT"}},
                        "transform": {
                            "scaleX": 1,
                            "scaleY": 1,
                            "translateX": 100,
                            "translateY": 100,
                            "unit": "PT"
                        }
                    }
                }
            },
            {
                "createShape": {
                    "objectId": content_shape_id,
                    "shapeType": "TEXT_BOX",
                    "elementProperties": {
                        "pageObjectId": slide_id,
                        "size": {"height": {"magnitude": 200, "unit": "PT"},
                                 "width": {"magnitude": 500, "unit": "PT"}},
                        "transform": {
                            "scaleX": 1,
                            "scaleY": 1,
                            "translateX": 100,
                            "translateY": 100,
                            "unit": "PT"
                        }
                    }
                }
            }
        ]
        service.presentations().batchUpdate(
            presentationId=presentation_id, body={"requests": shapes_creation_requests}
        ).execute()
        text_insertion_request= [
            {
                "insertText": {
                    "objectId": title_shape_id,
                    "insertionIndex": 0,
                    "text": slide_title
                }
            },
            {
            "insertText":{
            "objectId": content_shape_id,
            "insertionIndex": "0",
            "text": slide_text
                }
            }
        ]
        response = service.presentations().batchUpdate(
            presentationId=presentation_id, body={"requests": text_insertion_request}
        ).execute()
        return response
    except HttpError as error:
        raise Exception(f" Error {error}")

def add_content_in_slide(presentation_id: str, slide_id: str, slide_title: Optional[str]= '', slide_subtitle: Optional[str]= '', slide_body_text: Optional[str]= '')->dict:
    """
    This function basically insert the content in the slide's Title and Body.
    It takes Slide title and body text; finds the appropriate placeholders, if present it insert the title
    and body text in the appropriate placeholders.
    This is the main difference between this function and add_content_in_empty_slide that It will insert the title
    and body text if there are placeholders for the title and body on the other hand add_content_in_empty_slide will
    make the text boxes and placeholders to insert the text.

    It will take the slide_id and will insert the title and body text in that specific slide.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID where the content will be added.
        slide_title (str): The title of the content in the slide. Optional as all slides may not have title.
        slide_subtitle (str): The subtitle of the content in the slide. Optional as all slides may not have subtitle.
        slide_body_text (str): The text of the body in the slide. Optional as all slides may not have body.

    Returns:
        str: The presentation ID.
    
    Example:
        ```python
        def test_add_content():
            try:
                body= '''
                - Hello 1 
                - Hello 2
                - Hello 3
                '''
                content_addition = add_content_in_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_1',
                    slide_title= 'Slide Title',
                    slide_subtitle= 'Slide Subtitle',
                    slide_body_text= body
                )
                return f'Test case passed: {content_addition}'
            except Exception as e:
                return f'Error Inserting text to slide: {e}'
        ```
    """
    try:
        service= get_service('slides')
        presentation= get_presentation(presentation_id= presentation_id)['presentation_data']
        slides_data = presentation.get('slides')
        for slide in slides_data:
            if slide['objectId']== slide_id:
                for page_element in slide['pageElements']:
                    if page_element['shape']['placeholder']['type']== 'BODY':
                        text_insertion_request = [
                            {
                                "insertText": {
                                    "objectId": page_element['objectId'],
                                    "insertionIndex": 0,
                                    "text": slide_body_text
                                }
                            }
                        ]
                        service.presentations().batchUpdate(
                            presentationId=presentation_id, body={"requests": text_insertion_request}
                        ).execute()
                    elif page_element['shape']['placeholder']['type'] == 'SUBTITLE':
                        text_insertion_request = [
                            {
                                "insertText": {
                                    "objectId": page_element['objectId'],
                                    "insertionIndex": 0,
                                    "text": slide_subtitle
                                }
                            }
                        ]
                        service.presentations().batchUpdate(
                            presentationId=presentation_id, body={"requests": text_insertion_request}
                        ).execute()
                    elif page_element['shape']['placeholder']['type'] in ('CENTERED_TITLE', 'TITLE'):
                        text_insertion_request = [
                            {
                                "insertText": {
                                    "objectId": page_element['objectId'],
                                    "insertionIndex": 0,
                                    "text": slide_title
                                }
                            }
                        ]
                        service.presentations().batchUpdate(
                            presentationId=presentation_id, body={"requests": text_insertion_request}
                        ).execute()
        return {
            'status': 'success',
            'message': 'Successfully added content in the slide'
        }
    except HttpError as error:
        raise Exception(f" Error {error}")

def delete_slide(presentation_id: str, slide_id: str)->dict:
    """
    To delete any slide of any presentation given slide id to be deleted and presentation id in which that slide is.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID.

    Returns:
        dict: Status and Confirmation message.
    
    Example:
        ```python
        def test_delete_slide():
            try:
                slide_creation = delete_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_1',
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error Deleting slide: {e}'
        ```
    """
    try:
        service= get_service('slides')
        requests= [
            {
                'deleteObject': {
                    'objectId': slide_id,
                }
            }
        ]
        service.presentations().batchUpdate(presentationId= presentation_id, body= {"requests": requests}).execute()
        return {
            'status': 'success',
            'message': 'Successfully deleted the slide.'
        }
    except HttpError as error:
        raise Exception(f" Error {error}")

def delete_presentation(presentation_id: str)->dict:
    """
    To delete presentation given presentation id of the presentation to be deleted.
    It will move the presentation to Trash, and it can be recovered from it.

    Args:
        presentation_id (str): The presentation ID.

    Returns:
        dict: Status and Confirmation message.
    
    Example:
        ```python
        def test_delete_presentation():
            try:
                slide_creation = delete_presentation(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error Deleting Presentation: {e}'
        ```
    """
    try:
        service= get_service('drive')
        service.files().update(fileId= presentation_id, body={"trashed": True}).execute()
        return {
            'status': 'success',
            'message': 'Successfully deleted the Presentation.'
        }
    except HttpError as error:
        raise Exception(f" Error {error}")
