<script setup>
import NixCode from "./NixCode.vue"
import NixForm from "./NixForm.vue"
import { provide, ref } from 'vue'

const availableLanguages = {
  'en_US.UTF-8': 'English',
  'fr_FR.UTF-8': 'Francais'
}
const availableTimezones = Intl.supportedValuesOf('timeZone') 
let nixin = {
  netconf: 'autoconfig',
  networkingHostname: '',
  networkingDomain: 'nixin.local',
  availableBundles: [
    {
    "id": "writeCollectively",
    "name": "Write collectively : pads",
    "services": [
      'hedgedoc', 'nextcloud'
    ]
    },
    {
      "id": "forge",
      "name": "Forge : git repo, CI/CD workers, and NixiN",
      "services": [
        'forgejo', 'forgejorunner', 'nixin'
      ]

    },
    {
      "id": "socialMedia",
      "name": "Social media: hosted social medias in activitypub web-apps",
      "services": [
        'gotosocial', 'peertube', 'lemmy'
      ]

    }],
  availableServices: [
    {
    "id": "hedgedoc",
    "name": "Hedgedoc : realtime collaborative markdown editor"
    },
    {
      "id": "forgejo",
      "name": "Forgejo : git hosting"
    },
    {
      "id": "forgejorunner",
      "name": "Forgejo runner : CD/CI runner for Forgejo"
    },
    {
      "id": "gotosocial",
      "name": "Gotosocial : personal light activityPub social media"
    },
    {
      "id": "peertube",
      "name": "Peertube : video hosting platform with activityPub"
    },
    {
      "id": "lemmy",
      "name": "Lemmy : reddit alternative with activityPub"
    },
    {
      "id": "nextcloud",
      "name": "Nextcloud : personnal cloud"
    },
    {
      "id": "nixin",
      "name": "NixiN : web ui for configurations"
    }],
  bundles: [],
  services: [],
  timezone: 'UTC',
  locale: 'en_US.UTF-8',
  operatingUser: 'operator',
  operatingUserPassword: 'CHANGE ME !!!',
}
nixin.availableServices.forEach((s) => {
  s.inBundle = []
})
nixin.availableBundles.forEach((b) => {
  b.services.forEach((s) => {
    nixin.availableServices.find(item => item.id === s).inBundle.push(b.id);
  })
})
nixin=ref(nixin)
provide('nixin', nixin)

function netconfHasBeenChanged(val = '') {
  if (val === 'autoconfig') {
    nixin.networkingDomain = 'nixin.local'
  } else {
    nixin.networkingDomain = ''
  }
}

function selectServices(bundleId, services) {
  if (nixin.value.bundles.includes(bundleId)) {
    services.forEach((s) => {
      if (nixin.value.services.indexOf(s) === -1) {
        nixin.value.services.push(s)
      }
    })
  } else {
    services.forEach((s) => {
      const index = nixin.value.services.indexOf(s);
      if (index > -1) {
        nixin.value.services.splice(index, 1);
      }
    })
  }
}
</script>

<template>
  <h2>Networking</h2>
    <div class="form-cell">
      <strong>Choose your network configuration</strong>
      <div>
      <label>
        <input type="radio" v-model="nixin.netconf" value="autoconfig"
          @click="netconfHasBeenChanged('autoconfig')">I'm a noob in network config, I trust you to provide networking
        for me (ipv6 only)</label>
    </div>
    <div>
      <label>
        <input type="radio" v-model="nixin.netconf" value="publicip" @click="netconfHasBeenChanged">My server
        has a public ip that I can provide
      </label>
    </div>
    <div>
      <label>
        <input type="radio" v-model="nixin.netconf" value="localnetwork" @click="netconfHasBeenChanged">My
        router is set so that my local machine is accessible on the public network
      </label>
    </div>
    <div>
      <label>
        <input type="radio" v-model="nixin.netconf" value="wireguard" @click="netconfHasBeenChanged">My server can use a wireguard server i can configure
      </label>
    </div>
  </div>
  <div class="form-row">
    <div class="form-cell">
      <label>Machine network name</label>
      <input required type="text" v-model="nixin.networkingHostname"
        placeholder="Give your machine a name without spaces, ponctuation or accents" />
    </div>
  </div>
  <input v-if="nixin.netconf === 'autoconfig'" type="hidden" value="distrilab.fr" />
  <div class="form-row" v-if="nixin.netconf !== 'autoconfig'">
    <div class="form-cell">
      <label>Domain name</label>
      <input required type="text" v-model="nixin.networkingDomain" placeholder="ex: distrilab.fr" />
    </div>
  </div>

  <h2>Usage bundles</h2>
  <div class="form-row">
    <div class="form-cell">
      <strong>Choose your usage bundles (multiple choices possible if your machine can handle it)</strong>
      <div v-for="bundle in nixin.availableBundles" :key="bundle">
        <label>
          <input type="checkbox" v-model="nixin.bundles" :id="bundle.id" :value="bundle.id"
            @change="selectServices(bundle.id, bundle.services)" />
          {{ bundle.name }}
        </label>
      </div>
    </div>
  </div>

  <h2>Services</h2>
  <div v-if="nixin.bundles.length === 0">👆 Choose any upper bundle to make associated services appear.</div>
  <div v-for="service in nixin.availableServices" :key="service">
    <div v-if="service.inBundle && service.inBundle.some(ai => nixin.bundles.includes(ai))">
      <NixForm :service="service" />
    </div>
  </div>

  <h2>Other configuration</h2>
  <div class="form-row">
    <div class="form-cell">
      <label>Operating UNIX user name</label>
      <input required type="text" v-model="nixin.operatingUser" />
    </div>
  </div>
  <div class="form-row">
    <div class="form-cell">
      <label>Operating UNIX user password</label>
      <input required type="text" v-model="nixin.operatingUserPassword" />
    </div>
  </div>
  <div class="form-row">
    <div class="form-cell">
     <label>Timezone</label>
     <select v-model="nixin.timezone">
       <option v-for="tz in availableTimezones" :selected="nixin.timezone === tz" v-bind:value="tz">{{ tz }}</option>
     </select>
    </div>
  </div>
  <div class="form-row">
    <div class="form-cell">
     <label>Locale</label>
     <select v-model="nixin.locale">
       <option v-for="(lang, k) in availableLanguages" :selected="nixin.locale === k" v-bind:value="k">{{ lang }}</option>
     </select>
    </div>
  </div>

  <h2>Auto-generated configuration.nix file</h2>
  <pre class="nix-code">
    <code>
{ pkgs, ... }:

{
  networking.hosts = {
      "127.0.0.1" = [ "{{ nixin.networkingHostname }}.{{nixin.networkingDomain}}" ];
  };

  networking.hostName = "{{ nixin.networkingHostname }}";
  networking.domain = "{{ nixin.networkingDomain }}";
  networking.firewall = {
    allowedTCPPorts = [
      80
      443
    ];
  };

  time.timeZone = "{{ nixin.timezone }}";
  i18n.defaultLocale = "{{ nixin.locale }}";
<div v-for="(service) in nixin.services" :key="service">
<NixCode :service="service"/>
</div>

  users.users.{{ nixin.operatingUser }} = {
      isNormalUser = true;
      extraGroups = [ "wheel" ];
      initialPassword = "{{ nixin.operatingUserPassword }}";
  };

  security.sudo.extraRules= [
    {
      users = [ "{{ nixin.operatingUser }}" ];
      commands = [
        { 
          command = "ALL" ;
          options= [ "NOPASSWD" ]; # "SETENV" # Adding the following could be a good idea
        }
      ];
    }
  ];

  security.acme.defaults.email = "contact@nixin.local";
  security.acme.acceptTerms = true;

  services.nginx = {
    enable = true;

    # Use recommended settings
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;

    # Only allow PFS-enabled ciphers with AES256
    sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";

    virtualHosts."hedgedoc.nixin.local" = {
      forceSSL = true;
      enableACME = true;  
      root = "/var/www/hedgedoc";
      locations."/".proxyPass = "http://127.0.0.1:8001";
      locations."/socket.io/" = {
        proxyPass = "http://127.0.0.1:8001";
        proxyWebsockets = true;
        extraConfig = "proxy_ssl_server_name on;";
      };
    };
  };

  environment.systemPackages = with pkgs; [
    git
    wget
    tmux
    mosh
    htop
  ];  

  system.stateVersion = "24.05";
}
    </code>
  </pre>
</template>
