# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'etc'

WATCHMAN_SOURCE = ENV["WATCHMAN_SOURCE"]
DEV = ENV["DEV"]

def provision_ubuntu(config)
  if DEV
    system_update = ""
    dev_packages = <<-SHELL
      apt-get install -y emacs-nox htop tmux
    SHELL
  else
    system_update = <<-SHELL
      apt-get dist-upgrade -y
    SHELL
    dev_packages = ""
  end

  config.vm.provision "shell", inline: <<-SHELL
    set -x

    apt-get update

    #{system_update}

    # To avoid falling over during spiky RAM utilization, allow swap to
    # dynamically expand.
    apt-get install -y swapspace

    apt-get install -y gcc g++ m4 make pkg-config libssl-dev libz-dev

    su -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y' - vagrant

    #{dev_packages}
  SHELL
end

def provision_fedora(config)
  if DEV
    system_update = ""
    dev_packages = <<-SHELL
      dnf install -y emacs-nox htop tmux
    SHELL
  else
    system_update = <<-SHELL
      dnf update
    SHELL
    dev_packages = ""
  end

  config.vm.provision "shell", inline: <<-SHELL
    set -x

    #{system_update}

    dnf install -y python3-devel

    su -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y' - vagrant

    #{dev_packages}
  SHELL
end

def provision_freebsd(config)
  if DEV
    system_update = ""
    dev_packages = <<-SHELL
      pkg install -y emacs-nox htop tmux
    SHELL
  else
    system_update = <<-SHELL
      pkg upgrade -y
    SHELL
    dev_packages = ""
  end

  config.vm.provision "shell", inline: <<-SHELL
    set -x

    pkg update

    #{system_update}

    pkg install -y elfutils git gmake m4 patchelf python3

    su -l vagrant -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y'

    #{dev_packages}
  SHELL
end

def provider_linux(config)
  ["vmware_fusion", "vmware_workstation"].each do |provider|
    config.vm.provider provider do |vmware, override|
      # gcc uses 1.5 GB per process with Facebook style C++ :|
      cpu_count = Etc.nprocessors / 2
      vmware.cpus = cpu_count
      vmware.memory = 1536 * cpu_count
    end
  end
end

def provider_freebsd(config)
  ["vmware_fusion", "vmware_workstation"].each do |provider|
    config.vm.provider provider do |vmware, override|
      # FreeBSD and clang are quite memory-efficient relative to Linux
      # and gcc.
      cpu_count = Etc.nprocessors - 2
      vmware.cpus = cpu_count
      vmware.memory = 768 * cpu_count
    end
  end
end

def sync_fuse(config)
  if WATCHMAN_SOURCE.nil?
    return
  end
  config.vm.synced_folder WATCHMAN_SOURCE, "/home/vagrant/watchman"
end

def sync_nfs(config)
  if WATCHMAN_SOURCE.nil?
    return
  end
  config.vm.synced_folder WATCHMAN_SOURCE, "/home/vagrant/watchman", type: "nfs", nfs_version: 4, nfs_udp: false
end

Vagrant.configure("2") do |config|
  if WATCHMAN_SOURCE.nil?
    STDERR.puts "Please set WATCHMAN_SOURCE to the directory containing Watchman's source code"
  end

  # TODO: autogen.sh will put its built artifacts in /tmp by
  # default. The VMs automatically clear /tmp on boot, so it might
  # make sense to consider a different scratch path.

  config.vm.define "watchman-ubuntu-18", autostart: false do |ubuntu|
    ubuntu.vm.box = "bento/ubuntu-18.04"
    ubuntu.vm.hostname = "watchman-ubuntu-18"

    provision_ubuntu ubuntu
    provider_linux ubuntu
    sync_fuse ubuntu
  end

  config.vm.define "watchman-ubuntu-20", autostart: false do |ubuntu|
    ubuntu.vm.box = "bento/ubuntu-20.04"
    ubuntu.vm.hostname = "watchman-ubuntu-20"

    provision_ubuntu ubuntu
    provider_linux ubuntu
    sync_fuse ubuntu
  end

  config.vm.define "watchman-ubuntu-22", autostart: false do |ubuntu|
    ubuntu.vm.box = "bento/ubuntu-22.04"
    ubuntu.vm.hostname = "watchman-ubuntu-22"

    provision_ubuntu ubuntu
    provider_linux ubuntu
    sync_fuse ubuntu
  end

  fedora_vms = [
    {name: "watchman-fedora-35", box: "generic/fedora35"},
    {name: "watchman-fedora-36", box: "generic/fedora36"},
    {name: "watchman-fedora-37", box: "generic/fedora37"},
    # boxen needs many more packages installed by default. Maybe
    # generic/ will release a Fedora 38 box soon.
    {name: "watchman-fedora-38", box: "boxen/fedora-38-x86_64"},
  ]

  fedora_vms.each { |fedora_vm|
    config.vm.define fedora_vm[:name], autostart: false do |config|
      config.vm.box = fedora_vm[:box]
      config.vm.hostname = fedora_vm[:name]

      provision_fedora config
      provider_linux config
      sync_fuse config
    end
  }

  config.vm.define "watchman-freebsd" do |freebsd|
    freebsd.vm.box = "generic/freebsd12"
    freebsd.vm.hostname = "watchman-freebsd-12"

    provision_freebsd freebsd
    provider_freebsd freebsd
    sync_nfs freebsd
  end

end
