{ config, lib, ... }:
with lib;
let
  cfg = config.eboskma.klipper;
in
{
  options.eboskma.klipper = {
    enable = mkEnableOption "klipper";
  };

  config = mkIf cfg.enable {
    services = {
      klipper = {
        enable = true;
        firmwares = {
          mcu = {
            enable = true;
            configFile = ./firmware-config;
            serial = "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A600KWST-if00-port0";
          };
        };

        settings = {
          stepper_x = {
            step_pin = "PA3";
            dir_pin = "!PA1";
            enabe_pin = "!PA5";
            rotation_distance = 40;
            microsteps = 16;
            endstop_pin = "^PA0";
            position_min = -10;
            position_endstop = -10;
            position_max = 195;
            homing_speed = 50;
            homing_retract_dist = 5;
          };
          stepper_y = {
            step_pin = "PC6";
            dir_pin = "!PC4";
            enabe_pin = "!PA7";
            rotation_distance = 40;
            microsteps = 16;
            endstop_pin = "^PA4";
            position_min = 0;
            position_endstop = 0;
            position_max = 200;
            homing_speed = 50;
            homing_retract_dist = 5;
          };
          stepper_z = {
            step_pin = "PC0";
            dir_pin = "PG2";
            enabe_pin = "!PC2";
            rotation_distance = 2;
            microsteps = 16;
            endstop_pin = "^PC7";
            position_min = 0;
            position_endstop = 0;
            position_max = 180;
            homing_speed = 5;
            homing_retract_dist = 5;
          };

          extruder = {
            step_pin = "PL6";
            dir_pin = "!PL4";
            enable_pin = "!PG0";
            rotation_distance = 34.043;
            microsteps = 16;
            nozzle_diameter = 0.4;
            filament_diameter = 1.75;
            max_extrude_only_distance = 150;
            heater_pin = "PE4";
            sensor_type = "EPCOS 100K B57560G104F";
            sensor_pin = "PK0";
            control = "pid";
            pid_Kp = 12.33;
            pid_Ki = 0.51;
            pid_Kd = 74.5;
            min_temp = 0;
            max_temp = 250;
            max_extrude_cross_section = 5;
          };

          heater_bed = {
            heater_pin = "PG5";
            sensor_type = "ATC Semitec 104GT-2";
            sensor_pin = "PK2";
            control = "pid";
            pid_Kp = 234.88;
            pid_Ki = 42.79;
            pid_Kd = 322.28;
            min_temp = 0;
            max_temp = 120;
          };

          bed_screws = {
            screw1 = "20,7";
            screw2 = "190,7";
            screw3 = "190,180";
            screw4 = "20,180";
          };

          fan.pin = "PH4";

          mcu.serial = config.services.klipper.firmwares.mcu.serial;

          printer = {
            kinematics = "cartesian";
            max_velocity = 400;
            max_accel = 5000;
            max_z_velocity = 5;
            max_z_accel = 75;
          };

          display = {
            lcd_type = "hd44780";
            rs_pin = "PD1";
            e_pin = "PH0";
            d4_pin = "PH1";
            d5_pin = "PD0";
            d6_pin = "PE3";
            d7_pin = "PH3";
            encoder_pins = "PL7,PG1";
            click_pin = "^!PD2";
          };

          # These are necessary for Fluidd
          virtual_sdcard = {
            path = "/var/lib/klipper/gcode_files";
          };

          display_status = { };

          pause_resume = { };
        } // (import ./klipper-macros.nix);
      };

      moonraker = {
        enable = true;
        allowSystemControl = true;
        settings = {
          authorization = {
            cors_domains = [
              "*.local"
              "*://my.mainsail.xyz"
            ];

            trusted_clients = [
              "10.0.0.0/24"
              "10.1.0.0/24"
              "100.64.0.0/16"
              "127.0.0.0/8"
              "fe80::/10"
              "::1/128"
            ];
          };

          history = { };

          octoprint_compat = {
            enable_ufp = false;
          };

          zeroconf = { };
        };
      };

      mainsail = {
        enable = true;
        hostName = config.networking.hostName;
      };
    };
  };
}