# Copyright 2014 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.

"""Module contains a simple implementation of the registrationTickets RPC."""

import logging
from cherrypy import tools
import time
import uuid

import common
from fake_device_server import common_util
from fake_device_server import server_errors

REGISTRATION_PATH = 'registrationTickets'


class RegistrationTickets(object):
    """A simple implementation of the registrationTickets interface.

    A common workflow of using this API is:

    client: POST .../ # Creates a new ticket with id <id> claims the ticket.
    device: PATCH .../<id> with json blob # Populate ticket with device info
    device: POST .../<id>/finalize # Finalize the device registration.
    """
    # OAUTH2 Bearer Access Token
    TEST_ACCESS_TOKEN = '1/TEST-ME'

    # Needed for cherrypy to expose this to requests.
    exposed = True


    def __init__(self, resource, devices_instance, fail_control_handler):
        """Initializes a registration ticket.

        @param resource: A resource delegate.
        @param devices_instance: Instance of Devices class.
        @param fail_control_handler: Instance of FailControl.
        """
        self.resource = resource
        self.devices_instance = devices_instance
        self._fail_control_handler = fail_control_handler


    def _default_registration_ticket(self):
        """Creates and returns a new registration ticket."""
        current_time_ms = time.time() * 1000
        ticket = {'kind': 'clouddevices#registrationTicket',
                  'creationTimeMs': current_time_ms,
                  'expirationTimeMs': current_time_ms + (10 * 1000)}
        return ticket


    def _finalize(self, id, api_key, ticket):
        """Finalizes the ticket causing the server to add robot account info."""
        if 'userEmail' not in ticket:
            raise server_errors.HTTPError(400, 'Unclaimed ticket')

        robot_account_email = 'robot@test.org'
        robot_auth = uuid.uuid4().hex
        new_data = {'robotAccountEmail': robot_account_email,
                    'robotAccountAuthorizationCode':robot_auth}
        updated_data_val = self.resource.update_data_val(id, api_key, new_data)
        updated_data_val['deviceDraft'] = self.devices_instance.create_device(
            api_key, updated_data_val.get('deviceDraft'))
        return updated_data_val


    def _add_claim_data(self, data):
        """Adds userEmail to |data| to claim ticket.

        Raises:
            server_errors.HTTPError if there is an authorization error.
        """
        access_token = common_util.grab_header_field('Authorization')
        if not access_token:
            raise server_errors.HTTPError(401, 'Missing Authorization.')

        # Authorization should contain "<type> <token>"
        access_token_list = access_token.split()
        if len(access_token_list) != 2:
            raise server_errors.HTTPError(400, 'Malformed Authorization field')

        [type, code] = access_token_list
        # TODO(sosa): Consider adding HTTP WWW-Authenticate response header
        # field
        if type != 'Bearer':
            raise server_errors.HTTPError(403, 'Authorization requires '
                                          'bearer token.')
        elif code != RegistrationTickets.TEST_ACCESS_TOKEN:
            raise server_errors.HTTPError(403, 'Wrong access token.')
        else:
            logging.info('Ticket is being claimed.')
            data['userEmail'] = 'test_account@chromium.org'


    @tools.json_out()
    def GET(self, *args, **kwargs):
        """GET .../ticket_number returns info about the ticket.

        Raises:
            server_errors.HTTPError if the ticket doesn't exist.
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        return self.resource.get_data_val(id, api_key)


    @tools.json_out()
    def POST(self, *args, **kwargs):
        """Either creates a ticket OR claim/finalizes a ticket.

        This method implements the majority of the registration workflow.
        More specifically:
        POST ... creates a new ticket
        POST .../ticket_number/claim claims a given ticket with a fake email.
        POST .../ticket_number/finalize finalizes a ticket with a robot account.

        Raises:
            server_errors.HTTPError if the ticket should exist but doesn't
            (claim/finalize) or if we can't parse all the args.
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, operation = common_util.parse_common_args(
                args, kwargs, supported_operations=set(['finalize']))
        if operation:
            ticket = self.resource.get_data_val(id, api_key)
            if operation == 'finalize':
                return self._finalize(id, api_key, ticket)
            else:
                raise server_errors.HTTPError(
                        400, 'Unsupported method call %s' % operation)

        else:
            data = common_util.parse_serialized_json()
            if data is None or data.get('userEmail', None) != 'me':
                raise server_errors.HTTPError(
                        400,
                        'Require userEmail=me to create ticket %s' % operation)
            if [key for key in iter(data) if key != 'userEmail']:
                raise server_errors.HTTPError(
                        400, 'Extra data for ticket creation: %r.' % data)
            if id:
                raise server_errors.HTTPError(
                        400, 'Should not specify ticket ID.')

            self._add_claim_data(data)
            # We have an insert operation so make sure we have all required
            # fields.
            data.update(self._default_registration_ticket())

            logging.info('Ticket is being created.')
            return self.resource.update_data_val(id, api_key, data_in=data)


    @tools.json_out()
    def PATCH(self, *args, **kwargs):
        """Updates the given ticket with the incoming json blob.

        Format of this call is:
        PATCH .../ticket_number

        Caller must define a json blob to patch the ticket with.

        Raises:
            server_errors.HTTPError if the ticket doesn't exist.
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        if not id:
            server_errors.HTTPError(400, 'Missing id for operation')

        data = common_util.parse_serialized_json()

        return self.resource.update_data_val(
                id, api_key, data_in=data)


    @tools.json_out()
    def PUT(self, *args, **kwargs):
        """Replaces the given ticket with the incoming json blob.

        Format of this call is:
        PUT .../ticket_number

        Caller must define a json blob to patch the ticket with.

        Raises:
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        if not id:
            server_errors.HTTPError(400, 'Missing id for operation')

        data = common_util.parse_serialized_json()

        # Handle claiming a ticket with an authorized request.
        if data and data.get('userEmail') == 'me':
            self._add_claim_data(data)

        return self.resource.update_data_val(
                id, api_key, data_in=data, update=False)
