# pylint: disable=C0111,R0902,R0913
# Smartsheet Python SDK.
#
# Copyright 2017 Smartsheet.com, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"): you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import logging
from datetime import datetime

from . import fresh_operation


class Sights:

    """Class for handling Sights operations."""

    def __init__(self, smartsheet_obj):
        """Init Sights with base Smartsheet object."""
        self._base = smartsheet_obj
        self._log = logging.getLogger(__name__)

    def list_sights(
        self, page_size=None, page=None, include_all=None, modified_since=None
    ):
        """Get the list of all Sights the User has access to, in alphabetical
        order, by name.

        Args:
            page_size (int): The maximum number of items to
                return per page.
            page (int): Which page to return.
            include_all (bool): If true, include all results
                (i.e. do not paginate).
            modified_since(datetime): return sights modified since datetime

        Returns:
            IndexResult
        """
        _op = fresh_operation("list_sights")
        _op["method"] = "GET"
        _op["path"] = "/sights"
        _op["query_params"]["pageSize"] = page_size
        _op["query_params"]["page"] = page
        _op["query_params"]["includeAll"] = include_all
        if isinstance(modified_since, datetime):
            _op["query_params"]["modifiedSince"] = modified_since.isoformat()

        expected = ["IndexResult", "Sight"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def get_sight(self, sight_id, level=None, include=None):
        """Get the specified Sight.

        Args:
            sight_id (int): Sight ID
            level (int): compatibility level
            include (list[str]): optional include parameters

        Returns:
            Sight
        """
        _op = fresh_operation("get_sight")
        _op["method"] = "GET"
        _op["path"] = "/sights/" + str(sight_id)
        _op["query_params"]["include"] = include
        _op["query_params"]["level"] = level

        expected = "Sight"
        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def update_sight(self, sight_id, sight_obj):
        """Updates the specified Sight.

        Args:
            sight_id (int): Sight ID
            sight_obj (Sight): Sight object.

        Returns:
            Result
        """
        _op = fresh_operation("update_sight")
        _op["method"] = "PUT"
        _op["path"] = "/sights/" + str(sight_id)
        _op["json"] = sight_obj

        expected = ["Result", "Sight"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def delete_sight(self, sight_id):
        """Delete the specified Sight.

        Args:
            sight_id (int): Sight ID

        Returns:
            Result
        """
        _op = fresh_operation("delete_sight")
        _op["method"] = "DELETE"
        _op["path"] = "/sights/" + str(sight_id)

        expected = ["Result", None]
        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def copy_sight(self, sight_id, container_destination_obj):
        """Creates a copy of the specified Sight

        Args:
            sight_id (int): Sight ID
            container_destination_obj
                (ContainerDestination): Container Destination object.

        Returns:
            Result
        """
        _op = fresh_operation("copy_sight")
        _op["method"] = "POST"
        _op["path"] = "/sights/" + str(sight_id) + "/copy"
        _op["json"] = container_destination_obj

        expected = ["Result", "Sight"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def move_sight(self, sight_id, container_destination_obj):
        """Creates a copy of the specified Sight

        Args:
            sight_id (int): Sight ID
            container_destination_obj
                (ContainerDestination): Container Destination object.

        Returns:
            Result
        """
        _op = fresh_operation("move_sight")
        _op["method"] = "POST"
        _op["path"] = "/sights/" + str(sight_id) + "/move"
        _op["json"] = container_destination_obj

        expected = ["Result", "Sight"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def list_shares(
        self,
        sight_id,
        page_size=None,
        page=None,
        include_all=None,
        include_workspace_shares=False,
    ):
        """Get the list of all Users and Groups to whom the specified Sight is
        shared, and their access level.

        Args:
            sight_id (int): Sight ID
            page_size (int): The maximum number of items to
                return per page.
            page (int): Which page to return.
            include_all (bool): If true, include all results
                (i.e. do not paginate).
            include_workspace_shares(bool): Include Workspace shares

        Returns:
            IndexResult
        """
        _op = fresh_operation("list_shares")
        _op["method"] = "GET"
        _op["path"] = "/sights/" + str(sight_id) + "/shares"
        _op["query_params"]["pageSize"] = page_size
        _op["query_params"]["page"] = page
        _op["query_params"]["includeAll"] = include_all
        if include_workspace_shares:
            _op["query_params"]["include"] = "workspaceShares"

        expected = ["IndexResult", "Share"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def get_share(self, sight_id, share_id):
        """Get the specified Share.

        Args:
            sight_id (int): Sight ID
            share_id (str): Share ID

        Returns:
            Share
        """
        _op = fresh_operation("get_share")
        _op["method"] = "GET"
        _op["path"] = "/sights/" + str(sight_id) + "/shares/" + str(share_id)

        expected = "Share"
        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def share_sight(self, sight_id, share_obj, send_email=False):
        """Share the specified Sight.

        Share the specified Sight with the specified Users and
        Groups.

        Args:
            sight_id (int): Sight ID
            share_obj (Share): Share object.
            send_email (bool): Either true or false to
                indicate whether or not to notify the user by email. Default
                is false.

        Returns:
            Result
        """
        _op = fresh_operation("share_sight")
        _op["method"] = "POST"
        _op["path"] = "/sights/" + str(sight_id) + "/shares"
        _op["query_params"]["sendEmail"] = send_email
        _op["json"] = share_obj

        expected = ["Result", "Share"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def update_share(self, sight_id, share_id, share_obj):
        """Update the access level of a User or Group for the specified Sight.

        Args:
            sight_id (int): Sight ID
            share_id (str): Share ID
            share_obj (Share): Share object.

        Returns:
            Result
        """
        if not all(val is not None for val in ["sight_id", "share_id", "share_obj"]):
            raise ValueError(
                ("One or more required values are missing from call to " + __name__)
            )

        _op = fresh_operation("update_share")
        _op["method"] = "PUT"
        _op["path"] = "/sights/" + str(sight_id) + "/shares/" + str(share_id)
        _op["json"] = share_obj

        expected = ["Result", "Share"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def delete_share(self, sight_id, share_id):
        """Delete the specified Share.

        Args:
            sight_id (int): Sight ID
            share_id (str): Share ID

        Returns:
            Result
        """
        _op = fresh_operation("delete_share")
        _op["method"] = "DELETE"
        _op["path"] = "/sights/" + str(sight_id) + "/shares/" + str(share_id)

        expected = ["Result", None]
        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def get_publish_status(self, sight_id):
        """Get the Publish status of the Sight.

        Get the status of the Publish settings of the Sight,
        including URLs of any enabled publishings.

        Args:
            sight_id (int): Sight ID

        Returns:
            SightPublish
        """
        _op = fresh_operation("get_publish_status")
        _op["method"] = "GET"
        _op["path"] = "/sights/" + str(sight_id) + "/publish"

        expected = "SightPublish"
        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response

    def set_publish_status(self, sight_id, sight_publish_obj):
        """Set the publish status of the Sight and returns the new status,
        including the URLs of any enabled publishings.

        Args:
            sight_id (int): Sight ID
            sight_publish_obj (SightPublish): SightPublish object.

        Returns:
            Result
        """
        attributes = ["read_only_full_enabled", "read_only_full_accessible_by"]

        fetch_first = False
        # check for incompleteness, fill in from current status if necessary
        for attribute in attributes:
            val = getattr(sight_publish_obj, attribute, None)
            if val is None:
                fetch_first = True
                break

        if fetch_first:
            current_status = self.get_publish_status(sight_id).to_dict()
            current_status.update(sight_publish_obj.to_dict())
            sight_publish_obj = self._base.models.SightPublish(current_status)

        _op = fresh_operation("set_publish_status")
        _op["method"] = "PUT"
        _op["path"] = "/sights/" + str(sight_id) + "/publish"
        _op["json"] = sight_publish_obj

        expected = ["Result", "SightPublish"]

        prepped_request = self._base.prepare_request(_op)
        response = self._base.request(prepped_request, expected, _op)

        return response
