# Copyright 2019 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
#
#      http://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.
"""API module to serve cluster device service calls."""

import datetime
import json
import logging
import time

import endpoints
from protorpc import message_types
from protorpc import messages
from protorpc import remote

from tradefed_cluster.util import elasticsearch_client
from tradefed_cluster.util import ndb_shim as ndb


from tradefed_cluster import api_common
from tradefed_cluster import api_messages
from tradefed_cluster import common
from tradefed_cluster import datastore_entities
from tradefed_cluster import datastore_util
from tradefed_cluster import device_manager
from tradefed_cluster import env_config
from tradefed_cluster import note_manager


_DEFAULT_LIST_NOTES_COUNT = 10
_DEFAULT_LIST_DEVICE_COUNT = 100
_DEFAULT_LIST_HISTORIES_COUNT = 100


@api_common.tradefed_cluster_api.api_class(
    resource_name="devices", path="devices")
class ClusterDeviceApi(remote.Service):
  """A class for cluster device API service."""

  DEVICE_LIST_RESOURCE = endpoints.ResourceContainer(
      message_types.VoidMessage,
      lab_name=messages.StringField(1),
      hostname=messages.StringField(2),
      cluster_id=messages.StringField(3),
      device_types=messages.EnumField(
          api_messages.DeviceTypeMessage, 4, repeated=True),
      include_hidden=messages.BooleanField(5, default=False),
      include_offline_devices=messages.BooleanField(6, default=True),
      cursor=messages.StringField(7),
      count=messages.IntegerField(
          8, variant=messages.Variant.INT32,
          default=_DEFAULT_LIST_DEVICE_COUNT),
      product=messages.StringField(9),
      test_harnesses=messages.StringField(10, repeated=True),
      run_targets=messages.StringField(11, repeated=True),
      hostnames=messages.StringField(12, repeated=True),
      pools=messages.StringField(13, repeated=True),
      device_states=messages.StringField(14, repeated=True),
      host_groups=messages.StringField(15, repeated=True),
      device_serial=messages.StringField(16, repeated=True),
      flated_extra_info=messages.StringField(17),
      # TODO: Please use test_harnesses, this field is deprecated.
      test_harness=messages.StringField(18, repeated=True),
      elastic_query=messages.StringField(19),
  )

  def _GetValueFromExtraInfo(self, extra_info, key):
    """Fetches a value from extra info by the given key.

    Args:
      extra_info: a key value pair list.
      key: the key name in the extra info.

    Returns:
      a string value of the key.
    """
    for item in extra_info:
      if item.get("key") == key:
        return item.get("value")
    return None

  def FromElasticDocument(self, document):
    """Fetches a value from extra info by the given key.

    Args:
      document: a item of source from elastic.

    Returns:
      a DeviceInfo object
    """
    extra_info = document.get("extra_info")
    sim_state = self._GetValueFromExtraInfo(extra_info, "sim_state")
    sim_operator = self._GetValueFromExtraInfo(extra_info, "sim_operator")
    last_recovery_time = document.get("last_recovery_time")
    if last_recovery_time is not None:
      last_recovery_time = datetime.datetime.fromisoformat(last_recovery_time)
    return api_messages.DeviceInfo(
        device_serial=document.get("device_serial"),
        lab_name=document.get("lab_name"),
        cluster=document.get("cluster"),
        host_group=document.get("host_group"),
        hostname=document.get("hostname"),
        run_target=document.get("run_target"),
        pools=document.get("pools"),
        build_id=document.get("build_id"),
        product=document.get("product"),
        product_variant=document.get("product_variant"),
        sdk_version=document.get("sdk_version"),
        state=document.get("state"),
        timestamp=datetime.datetime.fromisoformat(document.get("timestamp")),
        hidden=document.get("hidden"),
        battery_level=document.get("battery_level"),
        mac_address=document.get("mac_address"),
        sim_state=sim_state,
        sim_operator=sim_operator,
        device_type=api_messages.DeviceTypeMessage(document.get("device_type")),
        extra_info=extra_info,
        test_harness=document.get("test_harness"),
        recovery_state=document.get("recovery_state"),
        flated_extra_info=document.get("flated_extra_info"),
        last_recovery_time=last_recovery_time,
        is_stub_device=document.get("is_stub_device"),
        display_serial=document.get("display_serial"),
        preconfigured_ip=document.get("preconfigured_ip"),
        preconfigured_device_num_offset=document.get(
            "preconfigured_device_num_offset"))

  @api_common.method(
      DEVICE_LIST_RESOURCE,
      api_messages.DeviceInfoCollection,
      path="/devices",
      http_method="GET",
      name="list")
  def ListDevices(self, request):
    """Fetches a list of devices from NDB.

    Args:
      request: an API request.

    Returns:
      a DeviceInfoCollection object.
    """
    logging.debug("ClusterDeviceApi.NDBListDevices request: %s", request)
    if (request.elastic_query is not None and
        env_config.CONFIG.use_elasticsearch):  # pytype: disable=attribute-error
      elastic_query = json.loads(request.elastic_query)
      client = elasticsearch_client.ElasticsearchClient()
      result, prev_cursor, next_cursor = client.Search(
          common.ELASTIC_INDEX_DEVICES, elastic_query)
      device_infos = [self.FromElasticDocument(d) for d in result]
      return api_messages.DeviceInfoCollection(
          device_infos=device_infos,
          next_cursor=next_cursor,
          prev_cursor=prev_cursor,
          more=bool(next_cursor))

    query = datastore_entities.DeviceInfo.query().order(
                datastore_entities.DeviceInfo.key)
    if request.lab_name:
      query = query.filter(
          datastore_entities.DeviceInfo.lab_name == request.lab_name)
    if request.cluster_id:
      query = query.filter(
          datastore_entities.DeviceInfo.clusters == request.cluster_id)
    if request.hostname:
      query = query.filter(
          datastore_entities.DeviceInfo.hostname == request.hostname)

    # We only consider device hidden here, since there is no simple way to do
    # join like operation in datastore. We tried fetching host and use
    # in(hostnames), but it was not scalable at all.
    if not request.include_hidden:
      query = query.filter(datastore_entities.DeviceInfo.hidden == False)  

    if request.product:
      query = query.filter(
          datastore_entities.DeviceInfo.product == request.product)

    if request.flated_extra_info:
      query = query.filter(datastore_entities.DeviceInfo.flated_extra_info ==
                           request.flated_extra_info)

    start_time = time.time()

    if len(request.pools) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.pools == request.pools[0])
    if len(request.device_states) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.state == request.device_states[0])
    if len(request.host_groups) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.host_group == request.host_groups[0])
    if len(request.device_types) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.device_type == request.device_types[0])
    test_harnesses = request.test_harness + request.test_harnesses
    if len(test_harnesses) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.test_harness == test_harnesses[0])
    if len(request.hostnames) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.hostname == request.hostnames[0])
    if len(request.run_targets) == 1:
      query = query.filter(
          datastore_entities.DeviceInfo.run_target == request.run_targets[0])
    if len(request.device_serial) == 1:
      query = query.filter(datastore_entities.DeviceInfo.device_serial ==
                           request.device_serial[0])

    def _PostFilter(device):
      if (request.pools and
          not set(device.pools).intersection(set(request.pools))):
        return
      if request.device_states and device.state not in request.device_states:
        return
      if request.host_groups and device.host_group not in request.host_groups:
        return
      if (not request.include_offline_devices and
          device.state not in common.DEVICE_ONLINE_STATES):
        return
      if (request.device_types and
          device.device_type not in request.device_types):
        return
      if test_harnesses and device.test_harness not in test_harnesses:
        return
      if request.hostnames and device.hostname not in request.hostnames:
        return
      if request.run_targets and device.run_target not in request.run_targets:
        return
      if (request.device_serial and
          device.device_serial not in request.device_serial):
        return
      return True

    devices, prev_cursor, next_cursor = datastore_util.FetchPage(
        query, request.count, request.cursor, result_filter=_PostFilter)

    logging.debug("Fetched %d devices in %r seconds.", len(devices),
                  time.time() - start_time)
    start_time = time.time()
    device_infos = [datastore_entities.ToMessage(d) for d in devices]
    logging.debug("Tranformed devices to messages in %r seconds.",
                  time.time() - start_time)
    return api_messages.DeviceInfoCollection(
        device_infos=device_infos,
        next_cursor=next_cursor,
        prev_cursor=prev_cursor,
        more=bool(next_cursor))

  DEVICE_GET_RESOURCE = endpoints.ResourceContainer(
      message_types.VoidMessage,
      device_serial=messages.StringField(1, required=True),
      include_notes=messages.BooleanField(2, default=False),
      include_history=messages.BooleanField(3, default=False),
      include_utilization=messages.BooleanField(4, default=False),
      hostname=messages.StringField(5),
  )

  @api_common.method(
      DEVICE_GET_RESOURCE,
      api_messages.DeviceInfo,
      path="{device_serial}",
      http_method="GET",
      name="get")
  def GetDevice(self, request):
    """Fetches the information and notes of a given device.

    Args:
      request: an API request.

    Returns:
      a DeviceInfo object.
    Raises:
      endpoints.NotFoundException: If the given device does not exist.
    """
    device_serial = request.device_serial
    device = device_manager.GetDevice(
        hostname=request.hostname, device_serial=device_serial)
    if not device:
      raise endpoints.NotFoundException(
          "Device {0} does not exist.".format(device_serial))

    device_info = datastore_entities.ToMessage(device)

    # TODO: deprecate "include_notes".
    if request.include_notes:
      device_notes = (
          datastore_entities.Note.query().filter(
              datastore_entities.Note.type == common.NoteType.DEVICE_NOTE)
          .filter(datastore_entities.Note.device_serial == device_serial).order(
              -datastore_entities.Note.timestamp))
      device_info.notes = [
          datastore_entities.ToMessage(note) for note in device_notes
      ]
    if request.include_history:
      histories = device_manager.GetDeviceStateHistory(device.hostname,
                                                       device_serial)
      device_info.history = [datastore_entities.ToMessage(h) for h in histories]
    if request.include_utilization:
      utilization = device_manager.CalculateDeviceUtilization(device_serial)
      device_info.utilization = utilization
    return device_info

  # TODO: deprecate "NewNote" endpoint.
  NEW_NOTE_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      user=messages.StringField(2, required=True),
      message=messages.StringField(3),
      offline_reason=messages.StringField(4),
      recovery_action=messages.StringField(5),
      offline_reason_id=messages.IntegerField(6),
      recovery_action_id=messages.IntegerField(7),
      lab_name=messages.StringField(8),
      timestamp=message_types.DateTimeField(9, required=True),
      hostname=messages.StringField(10),
  )

  @api_common.method(
      NEW_NOTE_RESOURCE,
      api_messages.Note,
      path="{device_serial}/note",
      http_method="POST",
      name="newNote")
  def NewNote(self, request):
    """Submits a note for this device.

    Args:
      request: an API request.

    Returns:
      an api_messages.Note object.
    """
    timestamp = request.timestamp
    # Datastore only accepts UTC times. Doing a conversion if necessary.
    if timestamp.utcoffset() is not None:
      timestamp = timestamp.replace(tzinfo=None) - timestamp.utcoffset()
    note = datastore_entities.Note(
        type=common.NoteType.DEVICE_NOTE,
        hostname=request.hostname,
        device_serial=request.device_serial,
        user=request.user,
        timestamp=timestamp,
        message=request.message,
        offline_reason=request.offline_reason,
        recovery_action=request.recovery_action)

    note.put()
    return datastore_entities.ToMessage(note)

  NOTE_ADD_OR_UPDATE_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      id=messages.IntegerField(2),
      user=messages.StringField(3, required=True),
      message=messages.StringField(4),
      offline_reason=messages.StringField(5),
      recovery_action=messages.StringField(6),
      offline_reason_id=messages.IntegerField(7),
      recovery_action_id=messages.IntegerField(8),
      lab_name=messages.StringField(9),
      hostname=messages.StringField(10),
      event_time=message_types.DateTimeField(11),
  )

  @api_common.method(
      NOTE_ADD_OR_UPDATE_RESOURCE,
      api_messages.Note,
      path="{device_serial}/notes",
      http_method="POST",
      name="addOrUpdateNote")
  def AddOrUpdateNote(self, request):
    """Add or update a device note.

    Args:
      request: an API request.

    Returns:
      an api_messages.Note.
    """
    time_now = datetime.datetime.utcnow()

    device_note_entity = datastore_util.GetOrCreateEntity(
        datastore_entities.Note,
        entity_id=request.id,
        device_serial=request.device_serial,
        hostname=request.hostname,
        type=common.NoteType.DEVICE_NOTE)
    device_note_entity.populate(
        user=request.user,
        message=request.message,
        timestamp=time_now,
        event_time=request.event_time)
    entities_to_update = [device_note_entity]

    try:
      offline_reason_entity = note_manager.PreparePredefinedMessageForNote(
          common.PredefinedMessageType.DEVICE_OFFLINE_REASON,
          message_id=request.offline_reason_id,
          lab_name=request.lab_name,
          content=request.offline_reason)
    except note_manager.InvalidParameterError as err:
      raise endpoints.BadRequestException("Invalid offline reason: [%s]" % err)
    if offline_reason_entity:
      device_note_entity.offline_reason = offline_reason_entity.content
      entities_to_update.append(offline_reason_entity)

    try:
      recovery_action_entity = note_manager.PreparePredefinedMessageForNote(
          common.PredefinedMessageType.DEVICE_RECOVERY_ACTION,
          message_id=request.recovery_action_id,
          lab_name=request.lab_name,
          content=request.recovery_action)
    except note_manager.InvalidParameterError as err:
      raise endpoints.BadRequestException("Invalid recovery action: [%s]" % err)
    if recovery_action_entity:
      device_note_entity.recovery_action = recovery_action_entity.content
      entities_to_update.append(recovery_action_entity)

    keys = ndb.put_multi(entities_to_update)
    device_note_msg = datastore_entities.ToMessage(device_note_entity)

    device = device_manager.GetDevice(
        device_serial=device_note_entity.device_serial)
    device_note_event_msg = api_messages.NoteEvent(
        note=device_note_msg,
        hostname=device.hostname,
        lab_name=device.lab_name,
        run_target=device.run_target)
    note_manager.PublishMessage(device_note_event_msg,
                                common.PublishEventType.DEVICE_NOTE_EVENT)

    note_key = keys[0]
    if request.id != note_key.id():
      # If ids are different, then a new note is created, we should create
      # a history snapshot.
      device_manager.CreateAndSaveDeviceInfoHistoryFromDeviceNote(
          request.device_serial, note_key.id())

    return device_note_msg

  @api_common.method(
      api_messages.BatchUpdateNotesWithPredefinedMessageRequest,
      api_messages.NoteCollection,
      path="notes:batchUpdateNotesWithPredefinedMessage",
      http_method="POST",
      name="batchUpdateNotesWithPredefinedMessage")
  def BatchUpdateNotesWithPredefinedMessage(self, request):
    """Batch update notes with the same predefined message.

    Args:
      request: an API request.

    Returns:
      an api_messages.NoteCollection object.
    """
    time_now = datetime.datetime.utcnow()

    device_note_entities = []
    for note in request.notes:
      note_id = int(note.id) if note.id is not None else None
      device_note_entity = datastore_util.GetOrCreateEntity(
          datastore_entities.Note,
          entity_id=note_id,
          device_serial=note.device_serial,
          hostname=note.hostname,
          type=common.NoteType.DEVICE_NOTE)
      device_note_entity.populate(
          user=request.user,
          message=request.message,
          timestamp=time_now,
          event_time=request.event_time)
      device_note_entities.append(device_note_entity)

    try:
      offline_reason_entity = note_manager.PreparePredefinedMessageForNote(
          common.PredefinedMessageType.DEVICE_OFFLINE_REASON,
          message_id=request.offline_reason_id,
          lab_name=request.lab_name,
          content=request.offline_reason,
          delta_count=len(device_note_entities))
    except note_manager.InvalidParameterError as err:
      raise endpoints.BadRequestException("Invalid offline reason: [%s]" % err)
    if offline_reason_entity:
      for device_note_entity in device_note_entities:
        device_note_entity.offline_reason = offline_reason_entity.content
      offline_reason_entity.put()

    try:
      recovery_action_entity = note_manager.PreparePredefinedMessageForNote(
          common.PredefinedMessageType.DEVICE_RECOVERY_ACTION,
          message_id=request.recovery_action_id,
          lab_name=request.lab_name,
          content=request.recovery_action,
          delta_count=len(device_note_entities))
    except note_manager.InvalidParameterError as err:
      raise endpoints.BadRequestException("Invalid recovery action: [%s]" % err)
    if recovery_action_entity:
      for device_note_entity in device_note_entities:
        device_note_entity.recovery_action = recovery_action_entity.content
      recovery_action_entity.put()

    note_keys = ndb.put_multi(device_note_entities)
    device_note_entities = ndb.get_multi(note_keys)
    note_msgs = []
    for device_note_entity in device_note_entities:
      device_note_msg = datastore_entities.ToMessage(device_note_entity)
      note_msgs.append(device_note_msg)

      device = device_manager.GetDevice(
          device_serial=device_note_entity.device_serial)
      device_note_event_msg = api_messages.NoteEvent(
          note=device_note_msg,
          hostname=device.hostname,
          lab_name=device.lab_name,
          run_target=device.run_target)
      note_manager.PublishMessage(
          device_note_event_msg, common.PublishEventType.DEVICE_NOTE_EVENT)

    for request_note, updated_note_key in zip(request.notes, note_keys):
      if not request_note.id:
        # If ids are not provided, then a new note is created, we should create
        # a history snapshot.
        device_manager.CreateAndSaveDeviceInfoHistoryFromDeviceNote(
            request_note.device_serial, updated_note_key.id())

    return api_messages.NoteCollection(
        notes=note_msgs, more=False, next_cursor=None, prev_cursor=None)

  NOTES_BATCH_GET_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      ids=messages.IntegerField(2, repeated=True),
  )

  @api_common.method(
      NOTES_BATCH_GET_RESOURCE,
      api_messages.NoteCollection,
      path="{device_serial}/notes:batchGet",
      http_method="GET",
      name="batchGetNotes")
  def BatchGetNotes(self, request):
    """Batch get notes of a device.

    Args:
      request: an API request.
    Request Params:
      device_serial: string, the serial of a lab device.
      ids: a list of strings, the ids of notes to batch get.

    Returns:
      an api_messages.NoteCollection object.
    """
    keys = [
        ndb.Key(datastore_entities.Note, entity_id)
        for entity_id in request.ids
    ]
    note_entities = ndb.get_multi(keys)
    note_msgs = [
        datastore_entities.ToMessage(entity)
        for entity in note_entities
        if entity and entity.device_serial == request.device_serial
    ]
    return api_messages.NoteCollection(
        notes=note_msgs, more=False, next_cursor=None, prev_cursor=None)

  NOTES_DELETE_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      ids=messages.IntegerField(2, repeated=True),
  )

  @api_common.method(
      NOTES_DELETE_RESOURCE,
      message_types.VoidMessage,
      path="{device_serial}/notes",
      http_method="DELETE",
      name="batchDeleteNotes")
  def BatchDeleteNotes(self, request):
    """Delete notes of a device.

    Args:
      request: an API request.
    Request Params:
      device_serial: string, the serial of a lab device.
      ids: a list of strings, the ids of notes to delete.

    Returns:
      a message_types.VoidMessage object.

    Raises:
      endpoints.BadRequestException, when request does not match existing notes.
    """
    keys = [
        ndb.Key(datastore_entities.Note, entity_id)
        for entity_id in request.ids
    ]
    note_entities = ndb.get_multi(keys)
    for key, note_entity in zip(keys, note_entities):
      if not note_entity:
        logging.warning("Note does not exist for key %s", key)
        continue
      if note_entity.device_serial != request.device_serial:
        raise endpoints.BadRequestException(
            "Note<id:{0}> does not exist under device<serial:{1}>.".format(
                key.id(), note_entity.device_serial))
    for key in keys:
      key.delete()
    return message_types.VoidMessage()

  NOTES_LIST_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      count=messages.IntegerField(2, default=_DEFAULT_LIST_NOTES_COUNT),
      cursor=messages.StringField(3),
      backwards=messages.BooleanField(4, default=False),
  )

  @api_common.method(
      NOTES_LIST_RESOURCE,
      api_messages.NoteCollection,
      path="{device_serial}/notes",
      http_method="GET",
      name="listNotes")
  def ListNotes(self, request):
    """List notes of a device.

    Args:
      request: an API request.

    Returns:
      an api_messages.NoteCollection object.
    """
    query = (
        datastore_entities.Note.query()
        .filter(datastore_entities.Note.type == common.NoteType.DEVICE_NOTE)
        .filter(datastore_entities.Note.device_serial == request.device_serial)
        .order(-datastore_entities.Note.timestamp))

    note_entities, prev_cursor, next_cursor = datastore_util.FetchPage(
        query, request.count, request.cursor, backwards=request.backwards)

    note_msgs = [
        datastore_entities.ToMessage(entity) for entity in note_entities
    ]
    return api_messages.NoteCollection(
        notes=note_msgs,
        more=bool(next_cursor),
        next_cursor=next_cursor,
        prev_cursor=prev_cursor)

  LATEST_NOTES_BATCH_GET_BY_DEVICE_RESOURCE = endpoints.ResourceContainer(
      device_serials=messages.StringField(1, repeated=True),)

  @api_common.method(
      LATEST_NOTES_BATCH_GET_BY_DEVICE_RESOURCE,
      api_messages.NoteCollection,
      path="latest_notes:batchGet",
      http_method="GET",
      name="batchGetLatestNotesByDevice")
  def BatchGetLatestNotesByDevice(self, request):
    """Batch get notes of a device.

    Args:
      request: an API request.
    Request Params:
      device_serial: string, the serial of a lab device.
      ids: a list of strings, the ids of notes to batch get.

    Returns:
      an api_messages.NoteCollection object.
    """
    note_entities = []
    for device_serial in request.device_serials:
      query = (
          datastore_entities.Note.query()
          .filter(datastore_entities.Note.type == common.NoteType.DEVICE_NOTE)
          .filter(datastore_entities.Note.device_serial == device_serial)
          .order(-datastore_entities.Note.timestamp))
      note_entities += list(query.fetch(1))
    note_msgs = [
        datastore_entities.ToMessage(entity) for entity in note_entities
    ]
    return api_messages.NoteCollection(
        notes=note_msgs, more=False, next_cursor=None, prev_cursor=None)

  DEVICE_SERIAL_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      hostname=messages.StringField(2),
  )

  @api_common.method(
      DEVICE_SERIAL_RESOURCE,
      api_messages.DeviceInfo,
      path="{device_serial}/remove",
      http_method="POST",
      name="remove")
  def Remove(self, request):
    """Remove this device .

    Args:
      request: an API request.

    Returns:
      an updated DeviceInfo
    Raises:
      endpoints.NotFoundException: If the given device does not exist.
    """
    device = device_manager.GetDevice(
        device_serial=request.device_serial, hostname=request.hostname)
    if not device:
      raise endpoints.NotFoundException("Device {0} {1} does not exist.".format(
          request.hostname, request.device_serial))
    device = device_manager.HideDevice(
        device_serial=device.device_serial, hostname=device.hostname)
    return datastore_entities.ToMessage(device)

  @api_common.method(
      DEVICE_SERIAL_RESOURCE,
      api_messages.DeviceInfo,
      path="{device_serial}/restore",
      http_method="POST",
      name="restore")
  def Restore(self, request):
    """Restore this device .

    Args:
      request: an API request.

    Returns:
      an updated DeviceInfo
    Raises:
      endpoints.NotFoundException: If the given device does not exist.
    """
    device = device_manager.GetDevice(
        device_serial=request.device_serial, hostname=request.hostname)
    if not device:
      raise endpoints.NotFoundException("Device {0} {1} does not exist.".format(
          request.hostname, request.device_serial))
    device = device_manager.RestoreDevice(
        device_serial=device.device_serial, hostname=device.hostname)
    return datastore_entities.ToMessage(device)

  HISTORIES_LIST_RESOURCE = endpoints.ResourceContainer(
      device_serial=messages.StringField(1, required=True),
      count=messages.IntegerField(2, default=_DEFAULT_LIST_HISTORIES_COUNT),
      cursor=messages.StringField(3),
      backwards=messages.BooleanField(4, default=False),
  )

  @api_common.method(
      HISTORIES_LIST_RESOURCE,
      api_messages.DeviceInfoHistoryCollection,
      path="{device_serial}/histories",
      http_method="GET",
      name="listHistories")
  def ListHistories(self, request):
    """List histories of a device.

    Args:
      request: an API request.

    Returns:
      an api_messages.DeviceInfoHistoryCollection object.
    """
    device = device_manager.GetDevice(device_serial=request.device_serial)
    if not device:
      raise endpoints.NotFoundException(
          f"Device {request.device_serial} does not exist.")

    query = (
        datastore_entities.DeviceInfoHistory.query(ancestor=device.key).order(
            -datastore_entities.DeviceInfoHistory.timestamp))
    histories, prev_cursor, next_cursor = datastore_util.FetchPage(
        query, request.count, request.cursor, backwards=request.backwards)
    history_msgs = [
        datastore_entities.ToMessage(entity) for entity in histories
    ]
    return api_messages.DeviceInfoHistoryCollection(
        histories=history_msgs,
        next_cursor=next_cursor,
        prev_cursor=prev_cursor)

  @api_common.method(
      api_messages.DeviceRecoveryStateRequests,
      message_types.VoidMessage,
      path="batchSetRecoveryState",
      http_method="POST",
      name="batchSetRecoveryState")
  def BatchSetRecoveryState(self, request):
    """Batch set recovery state for devices.

    Args:
      request: a DeviceRecoveryStateRequests.
    Returns:
      message_types.VoidMessage
    """
    device_manager.SetDevicesRecoveryState(
        request.device_recovery_state_requests)
    return message_types.VoidMessage()
