import math

import numpy as np

from qutrunk.circuit import Command
from .basicgate import BasicRotateGate


class R(BasicRotateGate):
    """
    Rotation alpha around the cos(beta)x + sin(beta)y axis

    Args:
        theta: the angle to rotate
        phi: define the axis cos(beta)x + sin(beta)y
    """

    def __init__(self, theta, phi):
        super().__init__()
        self.theta = theta
        self.phi = phi

    def __str__(self):
        return "R"

    def __or__(self, qubit):
        """
        Quantum logic gate operation

        Args:
            qubit: the quantum bit to aplly R gate.

        Example:
            R(theta, phi) * qr[0]
        """
        targets = [qubit.index]
        cmd = Command(self, targets, rotation=[self.theta, self.phi], inverse=self.is_inverse)
        qubit.circuit.append_cmd(cmd)

    def __mul__(self, qubit):
        """Overwrite * operator to achieve quantum logic gate operation, reuse __or__ operator implement"""
        self.__or__(qubit)

    @property
    def matrix(self):
        """Access to the matrix property of this gate."""
        theta, phi = float(self.theta), float(self.phi)
        cos = math.cos(theta / 2)
        sin = math.sin(theta / 2)
        exp_m = np.exp(-1j * phi)
        exp_p = np.exp(1j * phi)
        return np.array([[cos, -1j * exp_m * sin], [-1j * exp_p * sin, cos]])
