import pp


@pp.autoname
def wg(length=10, width=1):
    c = pp.Component()
    c.add_polygon([(0, 0), (length, 0), (length, width), (0, width)], layer=(1, 0))
    c.add_port(name="W0", midpoint=[0, width / 2], width=width, orientation=180)
    c.add_port(name="E0", midpoint=[length, width / 2], width=width, orientation=0)
    return c

"""
Explanation: Autoname
Problem:

In GDS different cells must have different names. Relying on the incrementals
naming convention can be dangerous when you merge masks that have different
cells build at different run times or if you Klayout for merging masks.
In GDS two cells cannot have the same name.

Solution: The decorator pp.autoname fixes both issues:

By giving the cell name depending on the parameters that you pass
By creating a cache of cells where we use the cell name as the key

Lets see how it works
End of explanation
"""


c = wg()
print(c)

c = wg(width=0.5)
print(c)

"""
Explanation: See how the cells get the name from the parameters that you pass them
End of explanation
"""


# Problem

c = pp.Component()
R1 = pp.c.rectangle()  # Creates a rectangle (Unique ID 1)
R2 = pp.c.rectangle()
# Try Create a new rectangle that we want to change (but has the same name so we will get R1 from the cache)

print(R1 == R2)
print(R1)
print(R2)

r1r = c << R1  # Add the first rectangle to c
r2r = c << R2  # Add the second rectangle to c
pp.qp(c)

# But now I want to rotate R2 -- I can't because it doesn't exist!
R2.rotate(45)
# I think I'm rotating a second rectangle, but actually R2 points to R1 even though I specifically tried to create two rectangles
pp.qp(c)

# Solution 1, you create a separate rotated cell which has a different name and only includes a rotated reference

c = pp.Component()
R1 = pp.c.rectangle(size=(2, 1))
# Creates a rectangle (Unique ID 1)

R2 = pp.c.rectangle(size=(2, 1))
# by default, `cache=True` this is actually returning the first rectangle!
R3 = pp.rotate.rotate(R2, 45)

print(R1 == R2)

print(R1)
print(R2)
print(R3)

r1r = c << R1  # Add the first rectangle to c
r2r = c << R3  # Add the second rectangle to c
pp.qp(c)

# Solution 2, you create a separate rectangle using cache=False
import pp

c = pp.Component()
R1 = pp.c.rectangle(size=(3, 1))  # Creates a rectangle (uuid)
R2 = pp.c.rectangle(size=(3, 1), name=f"{R1.name}_r", cache=False)
# with `cache=False` this is actually returning a new rectangle
# R2 has the parameters and would get the same name as R1 so you should give it a different name

print(R1 == R2)
print(R1)
print(R2)

r1r = c << R1  # Add the first rectangle to c
r2r = c << R2  # Add the second rectangle to c
R2.rotate(45)
pp.qp(c)

"""
Explanation: One challenge that you may face is when you actually want to have two different
cells with the same parameters
End of explanation
"""


c = pp.c.waveguide(pins=True)
pp.qp(c)
pp.show(c)

"""
Explanation: Adding port markers
When we decorate with autoname we can also pass a  pins flag that will
add port markers to our component and a device recognizion layer
End of explanation
"""


from pp.add_pins import add_pins_triangle

c = pp.c.waveguide(length=5, pins=True, pins_function=add_pins_triangle)
pp.qp(c)
pp.show(c)

"""
Explanation: We can even define the pins_function that we use to a custom function to add
markers
port
End of explanation
"""


@pp.autoname
def wg(length=10, width=1):
    c = pp.Component()
    c.add_polygon([(0, 0), (length, 0), (length, width), (0, width)], layer=(1, 0))
    print("calling wg function")
    return c

wg1 = wg()  # autoname builds a waveguide
print(wg1)

wg2 = wg()  # autoname returns the same waveguide as before

wg3 = wg(cache=False)
# Forces a rebuild of the cache. This is very helpful changing function `wg`

wg = wg() if callable(wg) else wg

wg = 2

wg

"""
Explanation: Cache
To avoid that 2 exact cells are not references of the same cell autoname has a
cache where if component has already been build it will return the component
from the cache
You can always over-ride this with cache = False This is helpful when you are
changing the code inside the function that is being cached.
End of explanation
"""


