# -*- coding: utf-8 -*-
#
# Copyright 2018 Google LLC
#
# 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
#
#     https://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 google.api_core.grpc_helpers
from google.api_core import operations_v1

from google.cloud.vision_v1p3beta1.proto import product_search_service_pb2_grpc


class ProductSearchGrpcTransport(object):
    """gRPC transport class providing stubs for
    google.cloud.vision.v1p3beta1 ProductSearch API.

    The transport provides access to the raw gRPC stubs,
    which can be used to take advantage of advanced
    features of gRPC.
    """
    # The scopes needed to make gRPC calls to all of the methods defined
    # in this service.
    _OAUTH_SCOPES = (
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/cloud-vision',
    )

    def __init__(self,
                 channel=None,
                 credentials=None,
                 address='vision.googleapis.com:443'):
        """Instantiate the transport class.

        Args:
            channel (grpc.Channel): A ``Channel`` instance through
                which to make calls. This argument is mutually exclusive
                with ``credentials``; providing both will raise an exception.
            credentials (google.auth.credentials.Credentials): The
                authorization credentials to attach to requests. These
                credentials identify this application to the service. If none
                are specified, the client will attempt to ascertain the
                credentials from the environment.
            address (str): The address where the service is hosted.
        """
        # If both `channel` and `credentials` are specified, raise an
        # exception (channels come with credentials baked in already).
        if channel is not None and credentials is not None:
            raise ValueError(
                'The `channel` and `credentials` arguments are mutually '
                'exclusive.', )

        # Create the channel.
        if channel is None:
            channel = self.create_channel(
                address=address,
                credentials=credentials,
            )

        # gRPC uses objects called "stubs" that are bound to the
        # channel and provide a basic method for each RPC.
        self._stubs = {
            'product_search_stub':
            product_search_service_pb2_grpc.ProductSearchStub(channel),
        }

        # Because this API includes a method that returns a
        # long-running operation (proto: google.longrunning.Operation),
        # instantiate an LRO client.
        self._operations_client = google.api_core.operations_v1.OperationsClient(
            channel)

    @classmethod
    def create_channel(cls,
                       address='vision.googleapis.com:443',
                       credentials=None):
        """Create and return a gRPC channel object.

        Args:
            address (str): The host for the channel to use.
            credentials (~.Credentials): The
                authorization credentials to attach to requests. These
                credentials identify this application to the service. If
                none are specified, the client will attempt to ascertain
                the credentials from the environment.

        Returns:
            grpc.Channel: A gRPC channel object.
        """
        return google.api_core.grpc_helpers.create_channel(
            address,
            credentials=credentials,
            scopes=cls._OAUTH_SCOPES,
        )

    @property
    def create_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Creates and returns a new ProductSet resource.

        Possible errors:

        * Returns INVALID_ARGUMENT if display_name is missing, or is longer than
        4096 characters.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].CreateProductSet

    @property
    def list_product_sets(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Lists ProductSets in an unspecified order.

        Possible errors:

        * Returns INVALID_ARGUMENT if page_size is greater than 100, or less
        than 1.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].ListProductSets

    @property
    def get_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Gets information associated with a ProductSet.

        Possible errors:

        * Returns NOT_FOUND if the ProductSet does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].GetProductSet

    @property
    def update_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Makes changes to a ProductSet resource.
        Only display_name can be updated currently.

        Possible errors:

        * Returns NOT_FOUND if the ProductSet does not exist.
        * Returns INVALID_ARGUMENT if display_name is present in update_mask but
        missing from the request or longer than 4096 characters.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].UpdateProductSet

    @property
    def delete_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Permanently deletes a ProductSet. All Products and ReferenceImages in the
        ProductSet will be deleted.

        The actual image files are not deleted from Google Cloud Storage.

        Possible errors:

        * Returns NOT_FOUND if the ProductSet does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].DeleteProductSet

    @property
    def create_product(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Creates and returns a new product resource.

        Possible errors:

        * Returns INVALID_ARGUMENT if display_name is missing or longer than 4096
        characters.
        * Returns INVALID_ARGUMENT if description is longer than 4096 characters.
        * Returns INVALID_ARGUMENT if product_category is missing or invalid.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].CreateProduct

    @property
    def list_products(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Lists products in an unspecified order.

        Possible errors:

        * Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].ListProducts

    @property
    def get_product(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Gets information associated with a Product.

        Possible errors:

        * Returns NOT_FOUND if the Product does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].GetProduct

    @property
    def update_product(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Makes changes to a Product resource.
        Only display_name, description and labels can be updated right now.

        If labels are updated, the change will not be reflected in queries until
        the next index time.

        Possible errors:

        * Returns NOT_FOUND if the Product does not exist.
        * Returns INVALID_ARGUMENT if display_name is present in update_mask but is
        missing from the request or longer than 4096 characters.
        * Returns INVALID_ARGUMENT if description is present in update_mask but is
        longer than 4096 characters.
        * Returns INVALID_ARGUMENT if product_category is present in update_mask.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].UpdateProduct

    @property
    def delete_product(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Permanently deletes a product and its reference images.

        Metadata of the product and all its images will be deleted right away, but
        search queries against ProductSets containing the product may still work
        until all related caches are refreshed.

        Possible errors:

        * Returns NOT_FOUND if the product does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].DeleteProduct

    @property
    def create_reference_image(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Creates and returns a new ReferenceImage resource.

        The ``bounding_poly`` field is optional. If ``bounding_poly`` is not specified,
        the system will try to detect regions of interest in the image that are
        compatible with the product_category on the parent product. If it is
        specified, detection is ALWAYS skipped. The system converts polygons into
        non-rotated rectangles.

        Note that the pipeline will resize the image if the image resolution is too
        large to process (above 50MP).

        Possible errors:

        * Returns INVALID_ARGUMENT if the image_uri is missing or longer than 4096
        characters.
        * Returns INVALID_ARGUMENT if the product does not exist.
        * Returns INVALID_ARGUMENT if bounding_poly is not provided, and nothing
        compatible with the parent product's product_category is detected.
        * Returns INVALID_ARGUMENT if bounding_poly contains more than 10 polygons.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].CreateReferenceImage

    @property
    def delete_reference_image(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Permanently deletes a reference image.

        The image metadata will be deleted right away, but search queries
        against ProductSets containing the image may still work until all related
        caches are refreshed.

        The actual image files are not deleted from Google Cloud Storage.

        Possible errors:

        * Returns NOT_FOUND if the reference image does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].DeleteReferenceImage

    @property
    def list_reference_images(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Lists reference images.

        Possible errors:

        * Returns NOT_FOUND if the parent product does not exist.
        * Returns INVALID_ARGUMENT if the page_size is greater than 100, or less
        than 1.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].ListReferenceImages

    @property
    def get_reference_image(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Gets information associated with a ReferenceImage.

        Possible errors:

        * Returns NOT_FOUND if the specified image does not exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].GetReferenceImage

    @property
    def add_product_to_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Adds a Product to the specified ProductSet. If the Product is already
        present, no change is made.

        One Product can be added to at most 100 ProductSets.

        Possible errors:

        * Returns NOT_FOUND if the Product or the ProductSet doesn't exist.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].AddProductToProductSet

    @property
    def remove_product_from_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Removes a Product from the specified ProductSet.

        Possible errors:

        * Returns NOT_FOUND If the Product is not found under the ProductSet.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].RemoveProductFromProductSet

    @property
    def list_products_in_product_set(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Lists the Products in a ProductSet, in an unspecified order. If the
        ProductSet does not exist, the products field of the response will be
        empty.

        Possible errors:

        * Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].ListProductsInProductSet

    @property
    def import_product_sets(self):
        """Return the gRPC stub for {$apiMethod.name}.

        Asynchronous API that imports a list of reference images to specified
        product sets based on a list of image information.

        The ``google.longrunning.Operation`` API can be used to keep track of the
        progress and results of the request.
        ``Operation.metadata`` contains ``BatchOperationMetadata``. (progress)
        ``Operation.response`` contains ``ImportProductSetsResponse``. (results)

        The input source of this method is a csv file on Google Cloud Storage.
        For the format of the csv file please see
        ``ImportProductSetsGcsSource.csv_file_uri``.

        Returns:
            Callable: A callable which accepts the appropriate
                deserialized request object and returns a
                deserialized response object.
        """
        return self._stubs['product_search_stub'].ImportProductSets
