from openflexure_microscope.api.utilities import JsonResponse
from openflexure_microscope.common.flask_labthings.resource import Resource
from openflexure_microscope.common.flask_labthings.find import find_device
from openflexure_microscope.common.flask_labthings.decorators import (
    use_args,
    marshal_with,
    doc,
)
from openflexure_microscope.common.flask_labthings import fields

from openflexure_microscope.utilities import axes_to_array, filter_dict

from flask import Blueprint, jsonify, request

import logging


class MoveStageAPI(Resource):
    @use_args(
        {
            "absolute": fields.Boolean(default=False, example=False, description="Move to an absolute position"),
            "x": fields.Int(default=0, example=100),
            "y": fields.Int(default=0, example=100),
            "z": fields.Int(default=0, example=20),
        }
    )
    def post(self, args):
        """
        Move the microscope stage in x, y, z
        """
        microscope = find_device("openflexure_microscope")

        # Handle absolute positioning (calculate a relative move from current position and target)
        if (args.get("absolute")) and (microscope.stage):  # Only if stage exists
            target_position = axes_to_array(args, ["x", "y", "z"])
            logging.debug("TARGET: {}".format(target_position))
            position = [
                target_position[i] - microscope.stage.position[i] for i in range(3)
            ]
            logging.debug("DELTA: {}".format(position))

        else:
            # Get coordinates from payload
            position = axes_to_array(args, ["x", "y", "z"], [0, 0, 0])

        logging.debug(position)

        # Move if stage exists
        if microscope.stage:
            # Explicitally acquire lock
            with microscope.stage.lock:
                microscope.stage.move_rel(position)
        else:
            logging.warning("Unable to move. No stage found.")

        return jsonify(microscope.status["stage"]["position"])


class ZeroStageAPI(Resource):
    def post(self):
        """
        Zero the stage coordinates.
        Does not move the stage, but rather makes the current position read as [0, 0, 0]
        """
        microscope = find_device("openflexure_microscope")
        microscope.stage.zero_position()

        return jsonify(microscope.status["stage"])
