"""
/*********************************************************************
* Copyright (c) 2023 the Qrisp Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
"""

# Created by ann81984 at 29.04.2022
import pytest
import numpy

from qrisp.interface import VirtualQiskitBackend
from qrisp import QuantumFloat, QuantumChar, QuantumArray, merge, x, h, OutcomeArray, multi_measurement


# check if the respone from QuantumArray.get_measurement() has the expected formet.
# Should return a list of tuples of the type (numpy.ndarray, float)
# ie. [(array([1,1,0]), 232), (array([1,1,3]), 115), ...]
def test_conditional_environments_example():
    
    qc = QuantumChar(name = "q ch")

    qc[:] = "f"

    qf = QuantumFloat(4,-1, signed = True)
    q_array = QuantumArray(qf, 4)


    h(qc[0])

    q_array[0] += -0.5


    with "f" == qc:
        h(q_array[0][0])
        
        
        with q_array[0] == -0.5:
            q_array[2].encode(-0.5)
            q_array[1] -= -1
            with q_array[1] == 1:
                q_array[3].init_from(q_array[2])
        
        #Test in-environment printing
        print(qc.qs)


    print(multi_measurement([qc, q_array]))
    assert multi_measurement([qc, q_array]) == {('e', OutcomeArray([-0.5,  0. ,  0. ,  0. ])): 0.5, ('f', OutcomeArray([-1.,  0.,  0.,  0.])): 0.25, ('f', OutcomeArray([-0.5,  1. , -0.5, -0.5])): 0.25}
    
    assert len(qc.qs.qv_list) == 5

    from qrisp import as_hamiltonian, QuantumBool, control
    @as_hamiltonian
    def dummy_d_function(i, j):
        return i*j

    def dummy_s_function(qf_list):
        
        m = len(qf_list)
        for i in range(m):
            dummy_d_function(qf_list[i], qf_list[(i+1)%m])
        

    qf_list = [QuantumFloat(2) for j in range(3)]

    qf_list[-1][:] = 1

    qbool = QuantumBool()
    h(qbool)
    with control(qbool[0]):
        dummy_s_function(qf_list)
        print(qbool.qs)

    h(qbool)
    
    assert qbool.most_likely() == False


    #-------
    
    a = QuantumFloat(2, name = "a")
    b = QuantumFloat(2, name = "b")
    c = QuantumFloat(1, name = "c")
    d = QuantumFloat(2, name = "d")

    a[:] = 1
    b[:] = 1
    c[:] = 1

    def test_f(a):
        return a == 1

    from qrisp import ConditionEnvironment, ControlEnvironment
    
    with test_f(a):
        with b == c:
            x(d)
            print(d.qs)
    
    #Test if uncomputation worked properly
    assert len(a.qs.qv_list) == 4
    
    #Test if condition environments get invoked properly
    with b == 2:
        assert isinstance(b.qs.env_stack[-1], ConditionEnvironment)
        temp = (d == 1)
        # print(d.qs)
        with temp:
            assert isinstance(d.qs.env_stack[-1], ControlEnvironment)
            x(c)
            # print(c.qs)

    assert len(a.qs.qv_list) == 5
    
    #----------
    a = QuantumFloat(2, signed = True)
    b = QuantumFloat(2, signed = True)
    c = QuantumFloat(1, signed = True)
    d = QuantumFloat(2, signed = True)
    

    a[:] = 1
    b[:] = 1
    c[:] = 1

    def test_f(a):
        return a == 1

    with test_f(a):
        with b == c:
            x(d)
            print(d.qs)

    assert len(a.qs.qv_list) == 4
    