# This code is part of Qiskit.
#
# (C) Copyright IBM 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Backend to emulate collective spin experiments."""

from typing import Optional

from qiskit.providers import ProviderV1 as Provider

from qiskit_cold_atom.spins.spin_simulator_backend import SpinSimulator


class CollectiveSpinSimulator(SpinSimulator):
    """Emulator backend of a spin device with collective spins of trapped BECs in optical tweezers.

    This backend will define a configuration with a set of supported gates and a line coupling map.
    At instantiation users can chose the length of the coupling map which by default is three. This
    backend is intended to be a realistic representation of a collective spin experiment with BECs.
    For a general spin simulator backend, use the SpinSimulator base class.
    """

    def __init__(self, n_tweezers: int = 3, provider: Optional[Provider] = None):
        """Create a new collective spin simulator backend.

        Args:
            n_tweezers: The number of optical tweezers.
            provider: The provider to which the backend may be added.
        """

        single_spin_coupl = [[i] for i in range(n_tweezers)]
        two_spin_coupl = [[i, i + 1] for i in range(n_tweezers - 1)] + [
            [i + 1, i] for i in range(n_tweezers - 1)
        ]

        configuration = {
            "backend_name": "collective_spin_simulator",
            "cold_atom_type": "spin",
            "backend_version": "0.0.1",
            "atomic_species": ["na"],
            "simulator": True,
            "local": True,
            "coupling_map": None,
            "description": "simulator of a collective hardware. Each wire in the circuit denotes the "
            "orientation of one collective spin in the hardware",
            "basis_gates": ["rlx", "rly", "rlz", "rlz2", "OAT", "rlzlz", "rlxly"],
            "memory": True,
            "n_qubits": 3,
            "conditional": False,
            "max_shots": 1e6,
            "max_experiments": 10,
            "open_pulse": False,
            "gates": [
                {
                    "coupling_map": single_spin_coupl,
                    "description": "local rotation of the coherent spin around x",
                    "name": "rlx",
                    "parameters": ["omega"],
                    "qasm_def": "gate rlx(omega) {}",
                },
                {
                    "coupling_map": single_spin_coupl,
                    "description": "local rotation of the coherent spin around y",
                    "name": "rly",
                    "parameters": ["delta"],
                    "qasm_def": "gate rly(delta) {}",
                },
                {
                    "coupling_map": single_spin_coupl,
                    "description": "local rotation of the coherent spin around z",
                    "name": "rlz",
                    "parameters": ["delta"],
                    "qasm_def": "gate rlz(delta) {}",
                },
                {
                    "coupling_map": single_spin_coupl,
                    "description": "local spin evolution generated by one-axis "
                    "twisting Hamiltonian Lz^2",
                    "name": "rlz2",
                    "parameters": ["chi"],
                    "qasm_def": "gate rlz2(chi) {}",
                },
                {
                    "coupling_map": single_spin_coupl,
                    "description": "local spin evolution generated by (chi*Lz^2 + "
                    "delta*Lz + omega*Lx)",
                    "name": "oat",
                    "parameters": ["chi", "delta", "omega"],
                    "qasm_def": "gate rot(chi, delta, omega) {}",
                },
                {
                    "coupling_map": two_spin_coupl,
                    "description": "ZZ-interaction coupling two collective spins",
                    "name": "rlzlz",
                    "parameters": ["gamma"],
                    "qasm_def": "gate rlzlz(gamma) {}",
                },
                {
                    "coupling_map": two_spin_coupl,
                    "description": "LXLY-interaction coupling two collective spins",
                    "name": "rlxly",
                    "parameters": ["gamma"],
                    "qasm_def": "gate rlxly(gamma) {}",
                },
            ],
            "supported_instructions": [
                "rlz",
                "rlx",
                "rly",
                "rlz2",
                "OAT",
                "rlzlz",
                "rlxly",
                "measure",
                "barrier",
            ],
        }

        super().__init__(config_dict=configuration, provider=provider)
