#import "@preview/cetz:0.4.2" as cetz
#import "@preview/zap:0.5.0" as zap
#import zap: interface

#let registerAllCustom() = {
  cetz.draw.set-ctx(ctx => {
    ctx.zap.style.insert("zweiTor", (
      scale: auto,
      fill: none,
      height: 10mm,
      width: 10mm,
    ))

    ctx.zap.style.insert("einTor", (
      scale: auto,
      fill: none,
      height: 3mm,
      width: 6mm,
    ))

    ctx.zap.style.insert("fet", (
      scale: auto,
      fill: none,
      height: 5mm,
      width: 10mm,
    ))


    for it in ("lnot", "land", "lnand", "lor", "lnor", "lxor", "lxnor") {
        ctx.zap.style.insert(it, (
          width: 0.7,
          min-height: 0.9,
          spacing: 0.4,
          padding: 0.25,
          fill: white,
          stroke: auto,
        )
      )
    }

    ctx
  })



}

#let einTor(name, node, flip: false, ..params) = {
  import cetz.draw: rect
  import zap: component


  // Drawing function
  let draw(ctx, position, style) = {
    rect(
      (-style.width/2, -style.height/2),
      (style.width/2, style.height/2),
      fill: style.fill
    )

    if(flip) {
      rect(
        ((style.width*0.7)/2, -(style.height)/2),
        (style.width/2, style.height/2),
        fill: black
      )
    } else {
      rect(
        (-(style.width)/2, -style.height/2),
        (-(style.width*0.6)/2, style.height/2),
        fill: black
      )
    }

    interface((-style.width / 2, -style.height / 2), (style.width / 2, style.height / 2), io: position.len() < 2)
  }

  // Component call
  component("einTor", name, node, draw: draw, ..params)
}

#let zweiTor(name, node, label, ..params) = {
  import cetz.draw: rect, anchor, content
  import zap: component


  // Drawing function
  let draw(ctx, position, style) = {
    rect(
      (-style.width/2, -style.height/2),
      (style.width/2, style.height/2),
      fill: style.fill
    )

    content((0,0), label)

    anchor("in0", (-style.width/2, -style.height*0.5/2))
    anchor("in1", (-style.width/2, style.height*0.5/2))
    anchor("out0", (style.width/2, -style.height*0.5/2))
    anchor("out1", (style.width/2, style.height*0.5/2))

    interface((-style.width / 2, -style.height / 2), (style.width / 2, style.height / 2), io: false)
  }

  // Component call
  component("zweiTor", name, node, draw: draw, ..params)
}

#let fet(name, node, type: "N", scale: 1, angle: 0, thickness: 0.5pt, ..params) = {
  import cetz.draw: line, circle, anchor, rotate
  import zap: component
  
  // Drawing function
  let draw(ctx, position, style) = {
    let zap-style = ctx.zap.style

    let height = style.height * scale;
    let width = style.width * scale;

    let wireThink = ctx.zap.style.wire.stroke.thickness;

    rotate(angle);

    if(type == "N") {
      line((0, height), (0, height*(1-0.45)), stroke: (thickness: wireThink))
    } else { 
      line((0, height), (0, height*(1-0.2)), stroke: (thickness: wireThink))
      circle((0, height*(1-0.3) - thickness/2), radius: (height/2)*0.2, stroke: (thickness: wireThink))
    }

    line(
      (width/2, 0), 
      (width*0.4/2, 0),
      (width*0.4/2, 0), 
      (width*0.4/2, height*(1-0.6)),
      (-width*0.4/2, height*(1-0.6)),
      (-width*0.4/2, 0),
      (-width/2, 0), stroke: (thickness: wireThink)
    )

    line(
      (width*0.42/2, height*(1-0.45)),
      (-width*0.42/2, height*(1-0.45)),
      stroke: (thickness: wireThink)
    )

    anchor("G", (0, height))
    anchor("D", (-width/2, 0))
    anchor("S", (width/2, 0))

    interface((-width / 2, -height / 2), (width / 2, height / 2), io: true)
  }

  // Component call
  component("fet", name, node, draw: draw, ..params)
}