# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Feedback client implementation for interacting with a human tester."""

import xmlrpclib

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.feedback import client


# Query return codes.
#
QUERY_RET_SUCCESS = 0
QUERY_RET_FAIL = 1
QUERY_RET_ERROR = 2


class Client(client.Client):
    """Human tester feedback implementation."""

    def __init__(self, test_name, dut_name, remote_addr):
        """Constructs the client object.

        @param test_name: The name of the test.
        @param dut_name: The name of the DUT.
        @param remote_addr: The 'name:port' of the remote feedback service host.
        """
        super(Client, self).__init__()
        self._client_id = '%s:%s' % (test_name, dut_name)
        self._remote_addr = remote_addr
        self._query_num = 0
        self._rpc_proxy = None
        self.tmp_dir = None
        self.dut_tmp_dir = None


    def _make_query_call(self, query_num, query_method, **kwargs):
        """Make an RPC query call (used by query objects).

        @param query_num: The unique query identifying number.
        @param query_method: The query method being called.

        @raise xmlrpclib.Error: An error during RPC call processing.
        """
        # XML-RPC does not support kwargs, so we just pass it as a dictionary.
        return self._rpc_proxy.query_call(self._client_id, query_num,
                                          query_method, kwargs)


    # Interface overrides.
    #
    def _initialize_impl(self, test, host):
        """Initializes the feedback object.

        Initializes an XML-RPC proxy and registers the client at the remote end.

        @param test: An object representing the test case.
        @param host: An object representing the DUT.
        """
        self._rpc_proxy = xmlrpclib.ServerProxy('http://%s' % self._remote_addr)
        try:
            self._rpc_proxy.new_client(self._client_id)
        except xmlrpclib.Error as e:
            raise error.TestError('Feedback client registration error: %s' % e)
        self.tmp_dir = test.tmpdir
        self.dut_tmp_dir = host.get_tmp_dir()


    def _new_query_impl(self, query_id):
        """Instantiates a new query.

        @param query_id: A query identifier.

        @return A query object.
        """
        if query_id in client.INPUT_QUERIES:
            query_cls = InputQuery
        elif query_id in client.OUTPUT_QUERIES:
            query_cls = OutputQuery
        else:
            raise error.TestError('Unknown query (%s)' % query_id)

        # Create, register and return a new query.
        self._query_num += 1
        try:
            self._rpc_proxy.new_query(self._client_id, query_id, self._query_num)
        except xmlrpclib.Error as e:
            raise error.TestError('Feedback query registration error: %s' % e)
        return query_cls(self, self._query_num)


    def _finalize_impl(self):
        """Finalizes the feedback object."""
        try:
            self._rpc_proxy.delete_client(self._client_id)
        except xmlrpclib.Error as e:
            raise error.TestError(
                    'Feedback client deregistration error: %s' % e)


class _Query(object):
    """Human tester feedback query base class."""

    def __init__(self, client, query_num):
        super(_Query, self).__init__()
        self.client = client
        self.query_num = query_num


    def _make_query_call(self, query_method, **kwargs):
        try:
            ret, desc = self.client._make_query_call(self.query_num,
                                                     query_method, **kwargs)
        except xmlrpclib.Error as e:
            ret, desc = QUERY_RET_ERROR, str(e)

        if ret == QUERY_RET_SUCCESS:
            return
        if ret == QUERY_RET_FAIL:
            raise error.TestFail('Tester feedback request failed: %s' % desc)
        if ret == QUERY_RET_ERROR:
            raise error.TestError('Tester feedback request error: %s' % desc)
        raise error.TestError('Unknown feedback call return code (%s)' % ret)


    # Interface overrides.
    #
    def _prepare_impl(self, **kwargs):
        self._make_query_call('prepare', **kwargs)


    def _validate_impl(self, **kwargs):
        self._make_query_call('validate', **kwargs)


class OutputQuery(_Query, client.OutputQuery):
    """Human tester feedback output query."""

    def __init__(self, client, query_num):
        super(OutputQuery, self).__init__(client, query_num)


class InputQuery(_Query, client.InputQuery):
    """Human tester feedback input query."""

    def __init__(self, client, query_num):
        super(InputQuery, self).__init__(client, query_num)


    # Interface override.
    #
    def _emit_impl(self):
        self._make_query_call('emit')
