from .tableau_rest_api_connection_26 import *


class TableauRestApiConnection27(TableauRestApiConnection26):
    def __init__(self, server, username, password, site_content_url=""):
        """
        :type server: unicode
        :type username: unicode
        :type password: unicode
        :type site_content_url: unicode
        """
        TableauRestApiConnection26.__init__(self, server, username, password, site_content_url)
        self.set_tableau_server_version("10.4")

    def update_datasource(self, datasource_name_or_luid, datasource_project_name_or_luid=None,
                          new_datasource_name=None, new_project_luid=None, new_owner_luid=None,
                          certification_status=None, certification_note=None):
        """
        :type datasource_name_or_luid: unicode
        :type datasource_project_name_or_luid: unicode
        :type new_datasource_name: unicode
        :type new_project_luid: unicode
        :type new_owner_luid: unicode
        :type certification_status: bool
        :type certification_note: unicode
        :rtype: etree.Element
        """
        self.start_log_block()
        if certification_status not in [None, False, True]:
            raise InvalidOptionException('certification_status must be None, False, or True')

        if self.is_luid(datasource_name_or_luid):
            datasource_luid = datasource_name_or_luid
        else:
            datasource_luid = self.query_datasource_luid(datasource_name_or_luid, datasource_project_name_or_luid)

        tsr = etree.Element("tsRequest")
        d = etree.Element("datasource")
        if new_datasource_name is not None:
            d.set('name', new_datasource_name)
        if certification_status is not None:
            d.set('isCertified', '{}'.format(str(certification_status).lower()))
        if certification_note is not None:
            d.set('certificationNote', certification_note)
        if new_project_luid is not None:
            p = etree.Element('project')
            p.set('id', new_project_luid)
            d.append(p)
        if new_owner_luid is not None:
            o = etree.Element('owner')
            o.set('id', new_owner_luid)
            d.append(o)

        tsr.append(d)

        url = self.build_api_url("datasources/{}".format(datasource_luid))
        response = self.send_update_request(url, tsr)
        self.end_log_block()
        return response

        #
        # Start Group Query Methods
        #

    def query_groups(self, name_filter=None, domain_name_filter=None, domain_nickname_filter=None, is_local_filter=None,
                     user_count_filter=None, minimum_site_role_filter=None, sorts=None):
        """
        :type name_filter: UrlFilter
        :type domain_name_filter: UrlFilter
        :type domain_nickname_filter: UrlFilter
        :type is_local_filter: UrlFilter
        :type user_count_filter: UrlFilter
        :type minimum_site_role_filter: UrlFilter
        :type sorts: list[Sort]
        :rtype: etree.Element
        """
        filter_checks = {'name': name_filter, 'domainName': domain_name_filter,
                         'domainNickname': domain_nickname_filter, 'isLocal': is_local_filter,
                         'userCount': user_count_filter, 'minimumSiteRole': minimum_site_role_filter}

        filters = self._check_filter_objects(filter_checks)

        self.start_log_block()
        groups = self.query_resource("groups", filters=filters, sorts=sorts)
        for group in groups:
            # Add to group-name : luid cache
            group_luid = group.get("id")
            group_name = group.get('name')
            self.group_name_luid_cache[group_name] = group_luid
        self.end_log_block()
        return groups

    def query_groups_json(self, name_filter=None, domain_name_filter=None, domain_nickname_filter=None,
                          is_local_filter=None, user_count_filter=None, minimum_site_role_filter=None,
                          sorts=None, page_number=None):
            """
            :type name_filter: UrlFilter
            :type domain_name_filter: UrlFilter
            :type domain_nickname_filter: UrlFilter
            :type is_local_filter: UrlFilter
            :type user_count_filter: UrlFilter
            :type minimum_site_role_filter: UrlFilter
            :type sorts: list[Sort]
            :type page_number: int
            :rtype: etree.Element
            """
            filter_checks = {'name': name_filter, 'domainName': domain_name_filter,
                             'domainNickname': domain_nickname_filter, 'isLocal': is_local_filter,
                             'userCount': user_count_filter, 'minimumSiteRole': minimum_site_role_filter}

            filters = self._check_filter_objects(filter_checks)

            self.start_log_block()
            groups = self.query_resource_json("groups", filters=filters, sorts=sorts, page_number=page_number)
            self.end_log_block()
            return groups

        # # No basic verb for querying a single group, so run a query_groups

    def query_group(self, group_name_or_luid):
        """
        :type group_name_or_luid: unicode
        :rtype: etree.Element
        """
        self.start_log_block()
        group = self.query_single_element_from_endpoint_with_filter('group', group_name_or_luid)
        # Add to group_name : luid cache
        group_luid = group.get("id")
        group_name = group.get('name')
        self.group_name_luid_cache[group_name] = group_luid

        self.end_log_block()
        return group

        # Groups luckily cannot have the same 'pretty name' on one site

    def query_group_luid(self, group_name):
        """
        :type group_name: unicode
        :rtype: unicode
        """
        self.start_log_block()
        if group_name in self.group_name_luid_cache:
            group_luid = self.group_name_luid_cache[group_name]
            self.log('Found group name {} in cache with luid {}'.format(group_name, group_luid))
        else:
            group_luid = self.query_single_element_luid_from_endpoint_with_filter('group', group_name)
            self.group_name_luid_cache[group_name] = group_luid
        self.end_log_block()
        return group_luid

    #
    # End Group Querying methods
    #

    #
    # Start Project Querying methods
    #

    def query_projects(self, name_filter=None, owner_name_filter=None, updated_at_filter=None, created_at_filter=None,
                       owner_domain_filter=None, owner_email_filter=None, sorts=None):
        """
        :type name_filter: UrlFilter
        :type owner_name_filter: UrlFilter
        :type updated_at_filter: UrlFilter
        :type created_at_filter: UrlFilter
        :type owner_domain_filter: UrlFilter
        :type owner_email_filter: UrlFilter
        :type sorts: list[Sort]
        :rtype: etree.Element
        """
        filter_checks = {'name': name_filter, 'ownerName': owner_name_filter,
                         'updatedAt': updated_at_filter, 'createdAt': created_at_filter,
                         'ownerDomain': owner_domain_filter, 'ownerEmail': owner_email_filter}

        filters = self._check_filter_objects(filter_checks)

        self.start_log_block()
        projects = self.query_resource("projects", filters=filters, sorts=sorts)
        self.end_log_block()
        return projects

    def query_projects_json(self, name_filter=None, owner_name_filter=None, updated_at_filter=None,
                            created_at_filter=None, owner_domain_filter=None, owner_email_filter=None, sorts=None,
                            page_number=None):
        """
        :type name_filter: UrlFilter
        :type owner_name_filter: UrlFilter
        :type updated_at_filter: UrlFilter
        :type created_at_filter: UrlFilter
        :type owner_domain_filter: UrlFilter
        :type owner_email_filter: UrlFilter
        :type sorts: list[Sort]
        :type page_number: int
        :rtype: etree.Element
        """
        filter_checks = {'name': name_filter, 'ownerName': owner_name_filter,
                         'updatedAt': updated_at_filter, 'createdAt': created_at_filter,
                         'ownerDomain': owner_domain_filter, 'ownerEmail': owner_email_filter}

        filters = self._check_filter_objects(filter_checks)

        self.start_log_block()
        projects = self.query_resource_json("projects", filters=filters, sorts=sorts, page_number=None)
        self.end_log_block()
        return projects

    def query_project_luid(self, project_name):
        """
        :type project_name: unicode
        :rtype: unicode
        """
        self.start_log_block()
        project_luid = self.query_single_element_luid_from_endpoint_with_filter('project', project_name)
        self.end_log_block()
        return project_luid

    def query_project(self, project_name_or_luid):
        """
        :type project_name_or_luid: unicode
        :rtype: Project21
        """
        self.start_log_block()
        if self.is_luid(project_name_or_luid):
            luid = project_name_or_luid
        else:
            luid = self.query_project_luid(project_name_or_luid)
        proj = self.get_published_project_object(luid, self.query_single_element_from_endpoint_with_filter('project',
                                                                                               project_name_or_luid))

        self.end_log_block()
        return proj

    def query_project_xml_object(self, project_name_or_luid):
        """
        :param project_name_or_luid: unicode
        :rtype: etree.Element
        """
        self.start_log_block()
        if self.is_luid(project_name_or_luid):
            luid = project_name_or_luid
        else:
            luid = self.query_project_luid(project_name_or_luid)
        proj_xml = self.query_single_element_from_endpoint_with_filter('project', luid)
        self.end_log_block()
        return proj_xml
    #
    # End Project Querying Methods
    #