(define-module (msg machine)
  #:use-module (ice-9 match)
  #:use-module (ice-9 rdelim)
  #:use-module (ice-9 textual-ports)
  #:use-module (system foreign)
  #:use-module (msg helpers)
  #:use-module (msg config)
  #:export (machine))


(define home-path (getenv "HOME"))
(define arch (run-shell-command "uname -m"))


(define cpu-conf #f)
(define mem-conf #f)

(define* (load-config #:optional args)
  (define config-file (format #f "~a/.guix/qemu/config.scm" home-path))
  (define loaded-config (manage-config config-file))
  (if (not (null? loaded-config))
      (begin
        (set! cpu-conf (cdr (assoc 'cpu loaded-config)))
        (set! mem-conf (cdr (assoc 'mem loaded-config)))
        #t)
      #f))


(define* (machine #:optional (args (command-line)))
  ;;(define clean-args (cdr args))
  (match args
    (("-h")
     (help))
    (("init" rest ...)
     (init rest))
    (("reinit")
     (stop)
     (clear-install)
     (init))
    (("start" rest ...)
     (start rest))
    (("stop")
     (stop))
    (("rm")
     (stop)
     (clear-install))
    (_
     (display "Please enter a valid command or -h for help.\n"))))




(define* (help)
  (display "\nHere are the available commands:\n\n")
  (display "start: Start the MSG envrionment.\n"))

(define* (clear-install)
  (let loop ()
    (display "This is a destructive command and will remove your entire Guix instance. Proceed? (y/n)\n")
    (define response (read-line))
    (cond
      ((string=? response "y")
       (system "rm -r ~/.guix")
       )
      ((string=? response "n")
       (display "Operation canceled.\n")
       (exit 0))
      (else
       (display "Please enter a valid response.\n")
       (loop)))))

(define* (start #:optional args)
  (define config (load-config))
  (if (not (directory-exists? (format #f "~a/.guix" home-path)))
      (begin
	(display "MSG not initialized. Please run `msg machine init` to continue. If you already tried to install and are receiving this message, try running `msg machine reinit`")
	(exit 0)))
  (cond
   ((string=? arch "arm64")
    (system (format #f "/opt/homebrew/bin/qemu-system-aarch64 \
             -machine virt,highmem=on \
             -accel hvf \
             -cpu host \
             -smp ~a \
             -display none \
             -hda $HOME/.guix/qemu/guix-user.qcow2 \
             -m ~aG \
             -virtfs local,path=/Users,security_model=mapped,mount_tag=macos \
             -bios /opt/homebrew/opt/qemu/share/qemu/edk2-aarch64-code.fd \
             -device virtio-net,netdev=vmnic \
             -netdev user,id=vmnic,hostfwd=tcp:127.0.0.1:9001-:22 &" cpu-conf mem-conf)))      
   ((string=? arch "x86_64")
    (system (format #f "/usr/local/bin/qemu-system-x86_64 \
             -machine type=q35,accel=hvf \
             -smp ~a \
             -hda $HOME/.guix/qemu/guix-user.qcow2 \
             -m ~aG \
             -display none \
             -cpu Nehalem \
             -virtfs local,path=/Users,security_model=mapped,mount_tag=macos \
             -device virtio-net,netdev=vmnic \
             -netdev user,id=vmnic,hostfwd=tcp:127.0.0.1:9001-:22 &" cpu-conf mem-conf))))
  (display "MSG has been started")
  )

(define* (stop)
  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo shutdown'"))


(define* (init #:optional args)

  (if (not (directory-exists? (format #f "~a/.guix" home-path)))
      (begin
	;; Grab ssh cert for installer
	(system "mkdir -p $HOME/.guix/qemu $HOME/.guix/home $HOME/.guix/ssh-cert")
	(system "ssh-keygen -R \"[127.0.0.1]:9001\"")
	;; Download system image and and start vm
	(cond
	 ((string=? arch "arm64")
	  (system "/opt/homebrew/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg-system-aarch64guix-installer.qcow2.tar.gz -O $HOME/.guix/qemu/guix.qcow2.tar.gz")
	  (system "tar -xvzf $HOME/.guix/qemu/guix.qcow2.tar.gz -C $HOME/.guix/qemu/")
	  (system "/opt/homebrew/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg-system-aarch64config.scm -O $HOME/.guix/home/config.scm")
	  ;; Get msg ssh-key
	  (system "/opt/homebrew/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg_rsa -O $HOME/.guix/ssh-cert/msg_rsa")
	  (system "chmod 400 ~/.guix/ssh-cert/msg_rsa ")
	  (system "/opt/homebrew/bin/qemu-system-aarch64 \
             -machine virt,highmem=on \
             -accel hvf \
             -cpu host \
             -smp 4 \
             -display none \
             -hda $HOME/.guix/qemu/guix-user.qcow2 \
             -m 4G \
             -virtfs local,path=$HOME/.guix/home,security_model=mapped,mount_tag=macos \
             -bios /opt/homebrew/opt/qemu/share/qemu/edk2-aarch64-code.fd \
             -device virtio-net,netdev=vmnic \
             -netdev user,id=vmnic,hostfwd=tcp:127.0.0.1:9001-:22 &")
	  (sleep 5)
	  (update-uid)

	  (build-msg)

	  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa root@127.0.0.1 -p 9001 'shutdown'")
	  (system "ssh-keygen -R \"[127.0.0.1]:9001\"")
	  (sleep 30)
	  (system "rm ~/.guix/qemu/guix-user.qcow2")
	  (system "mv ~/.guix/home/guix-user.qcow2 ~/.guix/qemu/")
	  (start)
	  (sleep 15)
	  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo mkdir /Users /boot/efi'")
	  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo mount /dev/vda1 /boot/efi'"))      
	 ((string=? arch "x86_64")
	  (system "/usr/local/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg-system-x86_64guix-installer.qcow2.tar.gz -O $HOME/.guix/qemu/guix.qcow2.tar.gz")
	  (system "tar -xvzf $HOME/.guix/qemu/guix.qcow2.tar.gz -C $HOME/.guix/qemu/")
	  (system "/usr/local/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg-system-x86_64config.scm -O $HOME/.guix/home/config.scm")
	  ;; Get msg ssh-key
	  (system "/usr/local/bin/wget https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg_rsa -O $HOME/.guix/ssh-cert/msg_rsa")
	  (system "chmod 400 ~/.guix/ssh-cert/msg_rsa ")
	  (system "/usr/local/bin/qemu-system-x86_64 \
             -machine type=q35,accel=hvf \
             -smp 4 \
             -hda $HOME/.guix/qemu/guix-installer.qcow2 \
             -m 4G \
             -display none \
             -cpu Nehalem \
             -virtfs local,path=$HOME/.guix/home,security_model=mapped,mount_tag=macos \
             -device virtio-net,netdev=vmnic \
             -netdev user,id=vmnic,hostfwd=tcp:127.0.0.1:9001-:22 &")
	  (sleep 5)
	  (update-uid)

	  (build-msg)

	  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa root@127.0.0.1 -p 9001 'shutdown'")
	  (system "ssh-keygen -R \"[127.0.0.1]:9001\"")
	  (sleep 30)
	  (system "rm ~/.guix/qemu/guix-installer.qcow2")
	  (system "mv ~/.guix/home/guix-user.qcow2 ~/.guix/qemu/")
	  (start)
	  (sleep 15)
	  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo mkdir /Users'"))
	 )
	


	(newline)
	(display "Reconfiguring MSG, this may take a few minutes...")
	(system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo guix system reconfigure --allow-downgrades /etc/config.scm'")
	(system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa admin@127.0.0.1 -p 9001 'sudo shutdown'")
	(display "\nMSG is ready to be started. Run 'msg machine start' to begin.\n"))
      (display "MSG already initialized. Please run `msg machine reinit` if you would like to recreate it."))


  )

(define (build-msg)
  ;; Build MSG
  (define* filename (run-shell-command "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa root@127.0.0.1 -p 9001 'guix system image -t qcow2 --save-provenance --image-size=100G /etc/config.scm'"))
  (system (format #f "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa root@127.0.0.1 -p 9001 'cp ~a /mnt/macos/guix-user.qcow2'" filename)))

(define (update-uid)
  ;; Update UID for msg image
  (system "sed -i.bak \"s/\\$UID/$(id -u)/g\" ~/.guix/home/config.scm && rm ~/.guix/home/config.scm.bak")
  (system "ssh -o StrictHostKeyChecking=no  -i $HOME/.guix/ssh-cert/msg_rsa root@127.0.0.1 -p 9001 'cp /mnt/macos/config.scm /etc/config.scm'"))