
Vagrant.configure(2) do |config|
  # TOHAVE DHCP assignations of IP adresses for all servers in the correct range
  # TOHAVE Verification of possible IP conflict
  # TOHAVE Dynamic machine dir
  # TODO adding checks for each confi and yml files
  # INFO All machines need to run to avoid issues
  # INFO Before you must install these plugins to speed up Vagrant provisioning
  # Ensure to have a key
  # vagrant plugin install vagrant-faster | WITHOUT VSCODE
  # vagrant plugin install vagrant-cachier

  # HACK MANAGER_IP & MANAGER_NAME need to be identical in the vagrantfile and variables.sh
  # HACK Precising names of VM to allow debugging without destroying previous machines
 
  # NOTE In shell provisionning , always a chmod +x if it's running on the MV. 
  # Configuration variables
  MANAGER_CPUS = 6
  MANAGER_MEM = 6000
  AGENT_CPUS = 2
  AGENT_MEM = 2048

  # Define the Wazuh server IP address (can be nil)
  MANAGER_IP = "192.168.56.13" # Change this to a specific IP if needed (Ranges: 192.168.56.0/21)
  MANAGER_NAME = "wazidx1"
  AGENT1_NAME = "wazagent1"
  AGENT2_NAME = "wazagent2"
  #config.cache.auto_detect = true

  # Set some variables
  etcHosts = ""

  # INFO Initial scripts | .sh paths do not include /vagrant | No comment in shell!

  # HERE Scripts to do before a up ##
  config.trigger.before :up do |trigger|
    trigger.run = {inline: "./setup_host.sh"}
  end

  # Common provisioning script that need to be run on the host machine
  common = <<-SHELL
    sudo apt update -qq 2>&1 >/dev/null
    sudo apt install -y -qq iftop curl software-properties-common git vim tree net-tools telnet git 2>&1 >/dev/null
    sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/g' /etc/ssh/sshd_config
    sudo systemctl restart sshd
  SHELL

  docker = <<-SHELL
    curl -fsSL https://get.docker.com -o get-docker.sh 2>&1 >/dev/null
    sudo sh get-docker.sh 2>&1 >/dev/null
    sudo usermod -aG docker vagrant
    sudo service docker start
    sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod 755 /usr/local/bin/docker-compose
  SHELL

  config.vm.box = "ubuntu/jammy64"
  config.vm.box_url = "ubuntu/jammy64"

  # Required functions
  def increment_ip(ip)
    parts = ip.split('.')
    parts[3] = (parts[3].to_i + 1).to_s
    parts.join('.')
  end

  # Set servers list and their parameters
  NODES = [
    { :hostname => MANAGER_NAME, :ip => MANAGER_IP, :cpus => MANAGER_CPUS, :mem => MANAGER_MEM, :type => "server" },
    { :hostname => AGENT1_NAME, :ip => nil, :cpus => AGENT_CPUS, :mem => AGENT_MEM, :type => "agent" },
    { :hostname => AGENT2_NAME, :ip => nil, :cpus => AGENT_CPUS, :mem => AGENT_MEM, :type => "agent" }
  ]

  # Define /etc/hosts for all servers
  previous_ip = nil

  NODES.each do |node|
    if node[:type] == "server"
      # Server node: use the predefined server IP
      node[:ip] = MANAGER_IP
      previous_ip = node[:ip]
      puts "Assigned server IP: #{node[:ip]} to #{node[:hostname]}"
    else
      # Agent node: assign IP dynamically by incrementing the previous IP
      node[:ip] = increment_ip(previous_ip)
      previous_ip = node[:ip]
      puts "Assigned agent IP: #{node[:ip]} to #{node[:hostname]}"
    end

    # Add the IP and hostname to /etc/hosts
    etcHosts += "echo '#{node[:ip]}   #{node[:hostname]}' >> /etc/hosts\n"
  end

  # Counter to track the number of VMs that have been set up
  setup_counter = 0

  # Run installation
  NODES.each_with_index do |node, index|
    config.vm.define node[:hostname] do |cfg|

      cfg.vm.hostname = node[:hostname]
      cfg.vm.network "private_network", ip: node[:ip]
      puts "Set #{node[:hostname]} IP to #{node[:ip]}"

      cfg.vm.provider "virtualbox" do |v|
        v.customize ["modifyvm", :id, "--cpus", node[:cpus]]
        v.customize ["modifyvm", :id, "--memory", node[:mem]]
        v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
        v.customize ["modifyvm", :id, "--name", node[:hostname]]
        v.customize ["modifyvm", :id, "--ioapic", "on"]
        v.customize ["modifyvm", :id, "--nictype1", "virtio"]
      end # End provider

      # For all
      # Install requirements
      cfg.vm.provision "shell", inline: <<-SHELL
        cd /vagrant/
        sudo apt update
        # Install Python 3.10 or higher if not already installed
        if ! command -v python3.10 &> /dev/null; then
          sudo apt install -y python3.10 python3.10-venv python3.10-dev
        fi
        
         # Ensure pip is installed for Python 3.10
        sudo apt install -y python3-pip

        sudo xargs apt install -y < requirements.txt
        sudo pip install -r src/requirements_python_VM.txt
      SHELL
      cfg.vm.provision :shell, :path => "VM/installers/install_braintech.sh"
      cfg.vm.provision :shell, :inline => etcHosts
      cfg.vm.provision :shell, :inline => common
      cfg.vm.provision :shell, :path => "VM/installers/install_node_exporter.sh"

      # Generate SSH keys and collect public keys
      cfg.vm.provision "shell", inline: <<-SHELL
        /vagrant/VM/setups/setup_ssh_keys.sh generate #{node[:hostname]}
        /vagrant/VM/setups/setup_ssh_keys.sh distribute #{node[:hostname]}
      SHELL

      if node[:type] == "server"

        # Installation #

        cfg.vm.provision :shell, :path => "VM/installers/install_wazuh_server.sh"

        ## HERE Pushing configuration files to server dedicated folder's ##
        cfg.vm.provision :shell, :path => "VM/configs/manager/config_manager.sh"

        ## HERE Cron Jobs ##
        cfg.vm.provision :shell, :path => "VM/setups/setup_cron_job.sh"

        ## HERE Cron Jobs ##
        cfg.vm.provision :shell, :path => "VM/setups/setup_log_rotation.sh"

      end

      if node[:type] == "agent"

        # Installation #

        cfg.vm.provision :shell, :path => "VM/installers/install_wazuh_agent.sh"

        ## HERE Configuration of the agent ##

        cfg.vm.provision :shell, :path => "VM/configs/agents/config_agent.sh"

        ## HERE Agents tests ##
        cfg.vm.provision "shell", inline: <<-SHELL
          sudo /vagrant/VM/tests/snort-scan.sh #{node[:ip]}
        SHELL
      end

    end # End config
  end # End nodes

  
  # Final setup and tests for vagrant configuration #
  config.trigger.after :up do |trigger|
    trigger.name = "Final setup"
    trigger.run = {inline: "./host/setups/setup_host_finish.sh"}
  end

  ## HERE Scripts do to after a destroy ##
  config.trigger.after :destroy do |trigger|
    trigger.run = {inline: "./cleaner.sh"}
  end

end