# 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):
        """Initializes a registration ticket.

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


    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.
        """
        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

        """
        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.

        """
        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.
        """
        id, api_key, _ = common_util.parse_common_args(args, kwargs)
        self.resource.del_data_val(id, api_key)
        self.commands_instance.remove_device(id)
