# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 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.

#from math import *
from math import sin, cos
from qiskit_metal import draw, Dict
from qiskit_metal.qlibrary.core.base import QComponent
import numpy as np

#from ... import config
#if not config.is_building_docs():
#    from qiskit_metal import is_true


class TransmonInterdigitated(QComponent):
    """
    The base "TransmonInterdigitated" inherits the "QComponent" class.

    This creates a transmon pocket with two large pads connected by a Josephson
    junction. Both pads have four interdigitated "fingers" which increase the
    capacitance of the structure. There are three coupling capacitor pads with qpins
    defined; these can be connected to other structures in a design using CPWs.

    Default Options:
        * pad_width: '1000um' -- width of the large rectanglular pads on either side
          of the junction
        * pad_height: '300um' -- height of the large rectanglular pads on either side
          of the junction
        * finger_width: '50um' -- width of the "finger" on either side of the junction
        * finger_height: '100um' -- height of the "finger" on the side of the junction
        * finger_space: '50um' -- height of the Josephson Junction (equivalently; space
          between two fingers)
        * pad_pos_x: '0um' -- the internal coordinate defining the center of the bottom
          rectangular pad
        * pad_pos_y: '0um' -- the internal coordinate defining the center of the bottom
          rectangular pad
        * comb_width: '50um' -- the width of the four interdigitated combs connected to
          either pad
        * comb_space_vert: '50um' -- the space between the edge of a comb and the edge of
          the opposite rectangular pad
        * comb_space_hor: '50um' -- the space between adjacent interdigitated comb structures
        * jj_width: '20um' -- the width of the Josephson Junction located between the two
          fingers of the device
        * cc_space: '50um' -- the space between the lower rectangular pad and the coupling
          capacitor below it
        * cc_width: '100um' -- the width of the coupling capacitor located below the bottom
          rectangular pad
        * cc_height: '100um' -- the height of the coupling capacitor located below the bottom
          rectangular pad
        * cc_topleft_space: '50um' -- the space between the upper rectangular pad and the top
          left coupling capacitor
        * cc_topleft_width: '100um' -- the width of the top left coupling capacitor pad
        * cc_topleft_height: '100um' -- the height of the top left coupling capacitor pad
        * cc_topright_space: '50um' -- the space between the upper rectangular pad and the
          top right coupling capacitor
        * cc_topright_width: '100um' -- the width of the top right coupling capacitor pad
        * cc_topright_height: '100um' -- the height of the top right coupling capacitor pad
        * position_x: '0um' -- the x-coordinate defining the center of the transmon pocket
          on the chip
        * position_y: '0um' -- the y-coordinate defining the center of the transmon pocket
          on the chip
        * rotation: '0.0' -- the angle at which the entire structure is rotated
        * rotation_top_pad: '180' -- internal coordinate defining the angle of rotation
          between top and bottom pads
        * layer: '1' -- all objcets are drawn assuming they are part of the same layer on a
          the chip
    """

    # Default drawing options
    default_options = Dict(pad_width='1000um',
                           pad_height='300um',
                           finger_width='50um',
                           finger_height='100um',
                           finger_space='50um',
                           pad_pos_x='0um',
                           pad_pos_y='0um',
                           comb_width='50um',
                           comb_space_vert='50um',
                           comb_space_hor='50um',
                           jj_width='20um',
                           cc_space='50um',
                           cc_width='100um',
                           cc_height='100um',
                           cc_topleft_space='50um',
                           cc_topleft_width='100um',
                           cc_topleft_height='100um',
                           cc_topright_space='50um',
                           cc_topright_width='100um',
                           cc_topright_height='100um',
                           position_x='0um',
                           position_y='0um',
                           rotation='0.0',
                           rotation_top_pad='180',
                           layer='1')
    """Default drawing options"""

    # Name prefix of component, if user doesn't provide name
    component_metadata = Dict(short_name='component')
    """Component metadata"""

    def make(self):
        """Convert self.options into QGeometry."""

        p = self.parse_options()  # Parse the string options into numbers

        # draw the lower pad as a rectangle
        pad_lower = draw.rectangle(p.pad_width, p.pad_height, p.pad_pos_x,
                                   p.pad_pos_y)

        # draw the lower finger as a rectangle
        finger_lower = draw.rectangle(
            p.finger_width, p.finger_height, p.pad_pos_x, p.pad_pos_y +
            0.49999 * (p.pad_height) + 0.49999 * (p.finger_height))

        # draw the Josephson Junction
        rect_jj = draw.rectangle(
            p.jj_width, p.finger_space, p.pad_pos_x,
            0.5 * (p.pad_height) + p.finger_height + 0.5 * (p.finger_space))

        # draw the first comb to the right of the lower finger as a rectangle
        comb1_lower = draw.rectangle(
            p.comb_width,
            (2 * p.finger_height + p.finger_space - p.comb_space_vert),
            (0.5 * p.finger_width + p.comb_space_hor + 0.5 * p.comb_width),
            (0.5 * p.pad_height + 0.5 *
             (p.pad_pos_y + 0.5 * (p.pad_height) + 0.5 * (p.finger_height))))

        # draw the second comb to the right of the lower finger by translating the first comb
        comb2_lower = draw.translate(comb1_lower,
                                     2.0 * (p.comb_space_hor + p.comb_width),
                                     0.0)

        # draw the first comb to the left of the lower finger
        comb3_lower = draw.rectangle(
            p.comb_width,
            (2 * p.finger_height + p.finger_space - p.comb_space_vert),
            (-0.5 * p.finger_width - 2.0 * p.comb_space_hor -
             1.5 * p.comb_width),
            (0.5 * p.pad_height + 0.5 *
             (p.pad_pos_y + 0.5 * (p.pad_height) + 0.5 * (p.finger_height))))

        # draw the second comb to the left of the lower finger
        comb4_lower = draw.translate(comb3_lower,
                                     -2.0 * (p.comb_space_hor + p.comb_width),
                                     0.0)

        coupling_capacitor = draw.rectangle(
            p.cc_width, p.cc_height, p.pad_pos_x,
            p.pad_pos_y - 0.5 * (p.pad_height) - p.cc_space - 0.5 * p.cc_height)

        cc_topleft = draw.rectangle(
            p.cc_topleft_width, p.cc_topleft_height,
            p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width,
            p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height +
            p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height)

        cc_topright = draw.translate(
            cc_topleft,
            p.pad_width - 0.5 * p.cc_topleft_width - 0.5 * p.cc_topright_width,
            0.0)

        # merge the bottom elements
        bottom = draw.union(pad_lower, finger_lower, comb1_lower, comb2_lower,
                            comb3_lower, comb4_lower)

        # create the top portion of the comb by translating and rotating
        # the bottom portion of the comb
        top = draw.translate(bottom, 0.0, p.pad_height + p.finger_space)
        top = draw.rotate(top, p.rotation_top_pad)

        # merge everything into a single design
        design = draw.union(bottom, top, rect_jj, coupling_capacitor,
                            cc_topleft, cc_topright)

        # draw the transmon pocket bounding box
        pocket = draw.rectangle(1.5 * p.pad_width, 5.0 * p.pad_height)

        # the origin is originally set to the middle of the lower pad.
        # Let's move it to the center of the JJ.
        design = draw.translate(
            design, 0.0,
            -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space)

        # now translate the final structure according to the user input
        design = draw.rotate(design, p.rotation, origin=(0, 0))
        design = draw.translate(design, p.position_x, p.position_y)

        pocket = draw.rotate(pocket, p.rotation, origin=(0, 0))
        pocket = draw.translate(pocket, p.position_x, p.position_y)

        geom = {'design': design}
        geom_pocket = {'pocket': pocket}
        self.add_qgeometry('poly', geom, layer=p.layer, subtract=False)
        self.add_qgeometry('poly', geom_pocket, layer=p.layer, subtract=True)

        ###################################################################

        # Add Qpin connections for coupling capacitors

        # define a function that both rotates and translates the
        # qpin coordinates
        def qpin_rotate_translate(x):
            """ This function rotates the coordinates of the three qpins
            according to the user inputs for "position_x", "position_y"
            and "rotation".
            """
            y = list(x)
            z = [0.0, 0.0]
            z[0] = y[0] * cos(p.rotation * 3.14159 / 180) - y[1] * sin(
                p.rotation * 3.14159 / 180)
            z[1] = y[0] * sin(p.rotation * 3.14159 / 180) + y[1] * cos(
                p.rotation * 3.14159 / 180)
            z[0] = z[0] + p.position_x
            z[1] = z[1] + p.position_y
            x = (z[0], z[1])
            return x

        # Add Qpin connections for the bottom coupling capacitor

        qp1a = (0.0,
                -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space)
        qp1b = (0.0, -0.5 * p.pad_height - p.cc_space - p.cc_height -
                0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space)

        # rotate and translate the qpin coordinates
        qp1a = qpin_rotate_translate(qp1a)
        qp1b = qpin_rotate_translate(qp1b)

        self.add_pin('pin1',
                     points=np.array([qp1a, qp1b]),
                     width=0.01,
                     input_as_norm=True)

        # Add Qpin connections for top left coupling capacitor

        qp2a = (p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width,
                p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height +
                p.finger_space + p.cc_topleft_space +
                0.5 * p.cc_topleft_height - 0.5 * p.pad_height -
                p.finger_height - 0.5 * p.finger_space)
        qp2b = (p.pad_pos_x - 0.5 * p.pad_width, p.pad_pos_y +
                1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space +
                p.cc_topleft_space + 0.5 * p.cc_topleft_height -
                0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space)

        qp2a = qpin_rotate_translate(qp2a)
        qp2b = qpin_rotate_translate(qp2b)

        self.add_pin('pin2',
                     points=np.array([qp2a, qp2b]),
                     width=0.01,
                     input_as_norm=True)

        # Add Qpin connections for top right coupling capacitor

        qp3a = (p.pad_pos_x + 0.5 * p.pad_width - 0.5 * p.cc_topleft_width,
                p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height +
                p.finger_space + p.cc_topleft_space +
                0.5 * p.cc_topleft_height - 0.5 * p.pad_height -
                p.finger_height - 0.5 * p.finger_space)
        qp3b = (p.pad_pos_x + 0.5 * p.pad_width, p.pad_pos_y +
                1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space +
                p.cc_topleft_space + 0.5 * p.cc_topleft_height -
                0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space)

        qp3a = qpin_rotate_translate(qp3a)
        qp3b = qpin_rotate_translate(qp3b)

        self.add_pin('pin3',
                     points=np.array([qp3a, qp3b]),
                     width=0.01,
                     input_as_norm=True)

[((81, 22, 105, 37), 'qiskit_metal.Dict', 'Dict', (), '', False, 'from qiskit_metal import draw, Dict\n'), ((109, 25, 109, 53), 'qiskit_metal.Dict', 'Dict', (), '', False, 'from qiskit_metal import draw, Dict\n'), ((118, 20, 119, 47), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(118, 35, 118, 46): 'p.pad_width', (118, 48, 118, 60): 'p.pad_height', (118, 62, 118, 73): 'p.pad_pos_x', (119, 35, 119, 46): 'p.pad_pos_y'}, {}), '(p.pad_width, p.pad_height, p.pad_pos_x, p.pad_pos_y)', False, 'from qiskit_metal import draw, Dict\n'), ((122, 23, 124, 67), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(123, 12, 123, 26): 'p.finger_width', (123, 28, 123, 43): 'p.finger_height', (123, 45, 123, 56): 'p.pad_pos_x', (123, 58, 124, 66): 'p.pad_pos_y + 0.49999 * p.pad_height + 0.49999 * p.finger_height'}, {}), '(p.finger_width, p.finger_height, p.pad_pos_x, p.pad_pos_y + \n    0.49999 * p.pad_height + 0.49999 * p.finger_height)', False, 'from qiskit_metal import draw, Dict\n'), ((127, 18, 129, 76), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(128, 12, 128, 22): 'p.jj_width', (128, 24, 128, 38): 'p.finger_space', (128, 40, 128, 51): 'p.pad_pos_x', (129, 12, 129, 75): '0.5 * p.pad_height + p.finger_height + 0.5 * p.finger_space'}, {}), '(p.jj_width, p.finger_space, p.pad_pos_x, 0.5 * p.pad_height +\n    p.finger_height + 0.5 * p.finger_space)', False, 'from qiskit_metal import draw, Dict\n'), ((132, 22, 137, 77), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(133, 12, 133, 24): 'p.comb_width', (134, 13, 134, 69): '2 * p.finger_height + p.finger_space - p.comb_space_vert', (135, 13, 135, 73): '0.5 * p.finger_width + p.comb_space_hor + 0.5 * p.comb_width', (136, 13, 137, 75): '0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * p.pad_height + 0.5 * p.\n    finger_height)'}, {}), '(p.comb_width, 2 * p.finger_height + p.finger_space - p.\n    comb_space_vert, 0.5 * p.finger_width + p.comb_space_hor + 0.5 * p.\n    comb_width, 0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * p.\n    pad_height + 0.5 * p.finger_height))', False, 'from qiskit_metal import draw, Dict\n'), ((140, 22, 142, 41), 'qiskit_metal.draw.translate', 'draw.translate', ({(140, 37, 140, 48): 'comb1_lower', (141, 37, 141, 76): '2.0 * (p.comb_space_hor + p.comb_width)', (142, 37, 142, 40): '0.0'}, {}), '(comb1_lower, 2.0 * (p.comb_space_hor + p.comb_width), 0.0)', False, 'from qiskit_metal import draw, Dict\n'), ((145, 22, 151, 77), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(146, 12, 146, 24): 'p.comb_width', (147, 13, 147, 69): '2 * p.finger_height + p.finger_space - p.comb_space_vert', (148, 13, 149, 31): '-0.5 * p.finger_width - 2.0 * p.comb_space_hor - 1.5 * p.comb_width', (150, 13, 151, 75): '0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * p.pad_height + 0.5 * p.\n    finger_height)'}, {}), '(p.comb_width, 2 * p.finger_height + p.finger_space - p.\n    comb_space_vert, -0.5 * p.finger_width - 2.0 * p.comb_space_hor - 1.5 *\n    p.comb_width, 0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * p.\n    pad_height + 0.5 * p.finger_height))', False, 'from qiskit_metal import draw, Dict\n'), ((154, 22, 156, 41), 'qiskit_metal.draw.translate', 'draw.translate', ({(154, 37, 154, 48): 'comb3_lower', (155, 37, 155, 77): '-2.0 * (p.comb_space_hor + p.comb_width)', (156, 37, 156, 40): '0.0'}, {}), '(comb3_lower, -2.0 * (p.comb_space_hor + p.comb_width), 0.0)', False, 'from qiskit_metal import draw, Dict\n'), ((158, 29, 160, 80), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(159, 12, 159, 22): 'p.cc_width', (159, 24, 159, 35): 'p.cc_height', (159, 37, 159, 48): 'p.pad_pos_x', (160, 12, 160, 79): 'p.pad_pos_y - 0.5 * p.pad_height - p.cc_space - 0.5 * p.cc_height'}, {}), '(p.cc_width, p.cc_height, p.pad_pos_x, p.pad_pos_y - 0.5 * p.\n    pad_height - p.cc_space - 0.5 * p.cc_height)', False, 'from qiskit_metal import draw, Dict\n'), ((162, 21, 166, 76), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(163, 12, 163, 30): 'p.cc_topleft_width', (163, 32, 163, 51): 'p.cc_topleft_height', (164, 12, 164, 70): 'p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width', (165, 12, 166, 75): 'p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height'}, {}), '(p.cc_topleft_width, p.cc_topleft_height, p.pad_pos_x - 0.5 *\n    p.pad_width + 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.\n    pad_height + 2.0 * p.finger_height + p.finger_space + p.\n    cc_topleft_space + 0.5 * p.cc_topleft_height)', False, 'from qiskit_metal import draw, Dict\n'), ((168, 22, 171, 16), 'qiskit_metal.draw.translate', 'draw.translate', ({(169, 12, 169, 22): 'cc_topleft', (170, 12, 170, 78): 'p.pad_width - 0.5 * p.cc_topleft_width - 0.5 * p.cc_topright_width', (171, 12, 171, 15): '0.0'}, {}), '(cc_topleft, p.pad_width - 0.5 * p.cc_topleft_width - 0.5 * p\n    .cc_topright_width, 0.0)', False, 'from qiskit_metal import draw, Dict\n'), ((174, 17, 175, 53), 'qiskit_metal.draw.union', 'draw.union', ({(174, 28, 174, 37): 'pad_lower', (174, 39, 174, 51): 'finger_lower', (174, 53, 174, 64): 'comb1_lower', (174, 66, 174, 77): 'comb2_lower', (175, 28, 175, 39): 'comb3_lower', (175, 41, 175, 52): 'comb4_lower'}, {}), '(pad_lower, finger_lower, comb1_lower, comb2_lower, comb3_lower,\n    comb4_lower)', False, 'from qiskit_metal import draw, Dict\n'), ((179, 14, 179, 72), 'qiskit_metal.draw.translate', 'draw.translate', ({(179, 29, 179, 35): 'bottom', (179, 37, 179, 40): '0.0', (179, 42, 179, 71): 'p.pad_height + p.finger_space'}, {}), '(bottom, 0.0, p.pad_height + p.finger_space)', False, 'from qiskit_metal import draw, Dict\n'), ((180, 14, 180, 50), 'qiskit_metal.draw.rotate', 'draw.rotate', ({(180, 26, 180, 29): 'top', (180, 31, 180, 49): 'p.rotation_top_pad'}, {}), '(top, p.rotation_top_pad)', False, 'from qiskit_metal import draw, Dict\n'), ((183, 17, 184, 52), 'qiskit_metal.draw.union', 'draw.union', ({(183, 28, 183, 34): 'bottom', (183, 36, 183, 39): 'top', (183, 41, 183, 48): 'rect_jj', (183, 50, 183, 68): 'coupling_capacitor', (184, 28, 184, 38): 'cc_topleft', (184, 40, 184, 51): 'cc_topright'}, {}), '(bottom, top, rect_jj, coupling_capacitor, cc_topleft, cc_topright)', False, 'from qiskit_metal import draw, Dict\n'), ((187, 17, 187, 70), 'qiskit_metal.draw.rectangle', 'draw.rectangle', ({(187, 32, 187, 49): '1.5 * p.pad_width', (187, 51, 187, 69): '5.0 * p.pad_height'}, {}), '(1.5 * p.pad_width, 5.0 * p.pad_height)', False, 'from qiskit_metal import draw, Dict\n'), ((191, 17, 193, 73), 'qiskit_metal.draw.translate', 'draw.translate', ({(192, 12, 192, 18): 'design', (192, 20, 192, 23): '0.0', (193, 12, 193, 72): '-0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space'}, {}), '(design, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p\n    .finger_space)', False, 'from qiskit_metal import draw, Dict\n'), ((196, 17, 196, 63), 'qiskit_metal.draw.rotate', 'draw.rotate', (), '', False, 'from qiskit_metal import draw, Dict\n'), ((197, 17, 197, 67), 'qiskit_metal.draw.translate', 'draw.translate', ({(197, 32, 197, 38): 'design', (197, 40, 197, 52): 'p.position_x', (197, 54, 197, 66): 'p.position_y'}, {}), '(design, p.position_x, p.position_y)', False, 'from qiskit_metal import draw, Dict\n'), ((199, 17, 199, 63), 'qiskit_metal.draw.rotate', 'draw.rotate', (), '', False, 'from qiskit_metal import draw, Dict\n'), ((200, 17, 200, 67), 'qiskit_metal.draw.translate', 'draw.translate', ({(200, 32, 200, 38): 'pocket', (200, 40, 200, 52): 'p.position_x', (200, 54, 200, 66): 'p.position_y'}, {}), '(pocket, p.position_x, p.position_y)', False, 'from qiskit_metal import draw, Dict\n'), ((241, 28, 241, 50), 'numpy.array', 'np.array', ({(241, 37, 241, 49): '[qp1a, qp1b]'}, {}), '([qp1a, qp1b])', True, 'import numpy as np\n'), ((261, 28, 261, 50), 'numpy.array', 'np.array', ({(261, 37, 261, 49): '[qp2a, qp2b]'}, {}), '([qp2a, qp2b])', True, 'import numpy as np\n'), ((281, 28, 281, 50), 'numpy.array', 'np.array', ({(281, 37, 281, 49): '[qp3a, qp3b]'}, {}), '([qp3a, qp3b])', True, 'import numpy as np\n'), ((220, 26, 220, 57), 'math.cos', 'cos', ({(220, 30, 220, 56): '(p.rotation * 3.14159 / 180)'}, {}), '(p.rotation * 3.14159 / 180)', False, 'from math import sin, cos\n'), ((220, 67, 221, 43), 'math.sin', 'sin', ({(221, 16, 221, 42): '(p.rotation * 3.14159 / 180)'}, {}), '(p.rotation * 3.14159 / 180)', False, 'from math import sin, cos\n'), ((222, 26, 222, 57), 'math.sin', 'sin', ({(222, 30, 222, 56): '(p.rotation * 3.14159 / 180)'}, {}), '(p.rotation * 3.14159 / 180)', False, 'from math import sin, cos\n'), ((222, 67, 223, 43), 'math.cos', 'cos', ({(223, 16, 223, 42): '(p.rotation * 3.14159 / 180)'}, {}), '(p.rotation * 3.14159 / 180)', False, 'from math import sin, cos\n')]