# 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 devices RPC."""

from cherrypy import tools
import logging

import common
from fake_device_server import common_util
from fake_device_server import resource_method
from fake_device_server import server_errors


# TODO(sosa): All access to this object should technically require auth. Create
# setters/getters for the auth token for testing.

DEVICES_PATH = 'devices'


class Devices(resource_method.ResourceMethod):
    """A simple implementation of the device interface.

    A common workflow of using this API is:

    POST .../ # Creates a new device with id <id>.
    PATCH ..../<id> # Update device state.
    GET .../<id> # Get device state.
    DELETE .../<id> # Delete the device.
    """

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


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

        @param resource: A resource delegate for storing devices.
        @param commands_instance: Instance of commands method class.
        @param oauth_instance: Instance of oauth class.
        @param fail_control_handler: Instance of FailControl.
        """
        super(Devices, self).__init__(resource)
        self.commands_instance = commands_instance
        self._oauth = oauth_instance
        self._fail_control_handler = fail_control_handler


    def _handle_state_patch(self, device_id, api_key, data):
        """Patch a device's state with the given update data.

        @param device_id: string device id to update.
        @param api_key: string api_key to support this resource delegate.
        @param data: json blob provided to patchState API.

        """
        # TODO(wiley) this.


    def _validate_device_resource(self, resource):
        # Verify required keys exist in the device draft.
        if not resource:
            raise server_errors.HTTPError(400, 'Empty device resource.')

        for key in ['name', 'deviceKind', 'channel']:
            if key not in resource:
                raise server_errors.HTTPError(400, 'Must specify %s' % key)

        # Add server fields.
        resource['kind'] = 'clouddevices#device'


    def create_device(self, api_key, device_config):
        """Creates a new device given the device_config.

        @param api_key: Api key for the application.
        @param device_config: Json dict for the device.
        @raises server_errors.HTTPError: if the config is missing a required key
        """
        logging.info('Creating device with api_key=%s and device_config=%r',
                     api_key, device_config)
        self._validate_device_resource(device_config)
        new_device = self.resource.update_data_val(None, api_key,
                                                   data_in=device_config)
        self.commands_instance.new_device(new_device['id'])
        return new_device


    @tools.json_out()
    def GET(self, *args, **kwargs):
        """GET .../(device_id) gets device info or lists all devices.

        Supports both the GET / LIST commands for devices. List lists all
        devices a user has access to, however, this implementation just returns
        all devices.

        Raises:
            server_errors.HTTPError if the device doesn't exist.
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        if id:
            return self.resource.get_data_val(id, api_key)
        else:
            # Returns listing (ignores optional parameters).
            listing = {'kind': 'clouddevices#devicesListResponse'}
            listing['devices'] = self.resource.get_data_vals()
            return listing


    @tools.json_out()
    def POST(self, *args, **kwargs):
        """Handle POSTs for a device.

        Supported APIs include:

        POST /devices/<device-id>/patchState

        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        args = list(args)
        device_id = args.pop(0) if args else None
        operation = args.pop(0) if args else None
        if device_id is None or operation != 'patchState':
            raise server_errors.HTTPError(400, 'Unsupported operation.')
        data = common_util.parse_serialized_json()
        access_token = common_util.get_access_token()
        api_key = self._oauth.get_api_key_from_access_token(access_token)
        self._handle_state_patch(device_id, api_key, data)
        return {'state': self.resource.get_data_val(device_id,
                                                    api_key)['state']}


    @tools.json_out()
    def PUT(self, *args, **kwargs):
        """Update an existing device using the incoming json data.

        On startup, devices make a request like:

        PUT http://<server-host>/devices/<device-id>

        {'channel': {'supportedType': 'xmpp'},
         'commandDefs': {},
         'description': 'test_description ',
         'deviceKind': 'test_device_kind',
         'displayName': 'test_display_name ',
         'id': '4471f7',
         'location': 'test_location ',
         'name': 'test_device_name',
         'state': {'base': {'firmwareVersion': '6771.0.2015_02_09_1429',
                            'isProximityTokenRequired': False,
                            'localDiscoveryEnabled': False,
                            'manufacturer': '',
                            'model': '',
                            'serialNumber': '',
                            'supportUrl': '',
                            'updateUrl': ''}}}

        This PUT has no API key, but comes with an OAUTH access token.

        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        device_id, _, _ = common_util.parse_common_args(args, kwargs)
        access_token = common_util.get_access_token()
        if not access_token:
            raise server_errors.HTTPError(401, 'Access denied.')
        api_key = self._oauth.get_api_key_from_access_token(access_token)
        data = common_util.parse_serialized_json()
        self._validate_device_resource(data)

        logging.info('Updating device with id=%s and device_config=%r',
                     device_id, data)
        new_device = self.resource.update_data_val(device_id, api_key,
                                                   data_in=data)
        return {}  # TODO(wiley) No idea what GCD returns here, leave it blank.


    def DELETE(self, *args, **kwargs):
        """Deletes the given device.

        Format of this call is:
        DELETE .../device_id

        Raises:
            server_errors.HTTPError if the device doesn't exist.
        """
        self._fail_control_handler.ensure_not_in_failure_mode()
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        self.resource.del_data_val(id, api_key)
        self.commands_instance.remove_device(id)
