{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      /etc/nixos/hardware-configuration.nix
    ];

  # Use the systemd-boot EFI boot loader.
  boot = {
    loader = {
      systemd-boot.enable = true;
      efi.canTouchEfiVariables = true;
      grub.device = "/dev/sda";
    };
    initrd = {
      luks.devices = [
        {
          name = "root";
          device = "/dev/sda2";
          preLVM = true;
        }
      ];
    };
  };

  hardware = {
    bluetooth.enable = true;
    pulseaudio = {
      package = pkgs.pulseaudioFull;
      enable = true;
    };
  };

  networking.hostName = "nixos"; # Define your hostname.
  networking.networkmanager.enable = true;

  # Auto-upgrade channel
  # https://nixos.org/nixos/manual/index.html#idm140737316795120
  system.autoUpgrade.enable = true;

  nix.gc = {
    automatic = true;
    dates = "03:15";
  };

  # Select internationalisation properties.
  i18n = {
    consoleFont = "Lat2-Terminus16";
    consoleKeyMap = "br-abnt2";
    defaultLocale = "en_US.UTF-8";
  };

  # Set your time zone.
  time.timeZone = "America/Sao_Paulo";

  virtualisation.docker.enable = true;
  virtualisation.virtualbox.host.enable = true;

  fonts.fonts = with pkgs; [
    source-code-pro
    fira-code
    fira-mono
    fira-code-symbols
    freefont_ttf
  ];

  environment.systemPackages =
    let pkgsUnstable = import(fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz) {};
    in with pkgs; [

    ## Personal data tools

    gitAndTools.git-open
    gitAndTools.gitFull
    gitAndTools.diff-so-fancy
    gitAndTools.git-annex
    gitAndTools.gitRemoteGcrypt
    gitAndTools.git-dit
    git-crypt
    git-lfs
    gnupg
    mr
    nextcloud-client
    borgbackup


    ## CLI tools

    bash
    bash-completion
    nix-bash-completions
    youtube-dl
    wget
    vim
    thefuck
    tmux
    tmuxinator
    sox                         # =play=
    gettext                     # =envsubst=
    ag
    gnugrep
    ack
    htop
    rlwrap
    awscli
    jq
    openvpn
    xclip
    bc                          # binary calculator used in nucli
    sassc
    watchman
    ipfs
    gnumake
    gcc
    psmisc                      # =killall=
    xorg.xkill
    autojump
    bfg-repo-cleaner
    pwgen
    gksu                        # =gksudo=
    gnome3.gconf                # https://github.com/NixOS/nixpkgs/issues/15978
    lsof
    pciutils
    python27Packages.pywatchman # =watchman-wait=
    libressl
    tree
    i2p
    libxml2                     # =xmllint=
    unzip                       # used by extract bash function and Clojure go-to-source
    odt2txt                     # used to diff odf files
    feh                         # simplistic image viewer
    nixUnstable                 # =nix=
    zip
    kubernetes
    zlib
    vagrant
    docker_compose
    docker-machine
    redis
    alsaUtils                   # for xmonad volume commands
    git-sizer
    multimarkdown               # =markdown=
    pup                         # command-line HTML parsing https://github.com/ericchiang/pup
    binutils-unwrapped          # =ar= command for cargo build
    ant
    nssTools                    # =pk12util=
    gitAndTools.hub             # GitHub helper
    insomnia
    bind                        # =dig=
    file
    gitlab-runner
    sshpass
    zathura                    # for viewing Emacs PDF files
    timidity
    notmuch
    isync
    cacert
    gtypist
    pandoc

    diffoscope                 #
    poppler_utils              # used by diffoscope for comparing PDF files
    pdftk                      #


    gnome3.libgnome-keyring
    gnome3.gnome-keyring

    ## Spell checking

    (aspellWithDicts (ps : with ps; [ en eo fr pt_BR ]))

    ## NixOS

    pypi2nix
    bundix
    nix-repl


    ## Music

    texlive.combined.scheme-full
    lilypond
    frescobaldi


    ## Programming tools

    sbcl
    stack
    leiningen
    python3
    python
    nodejs-8_x
    elixir
    openjdk
    solc
    bundler
    rustc
    rustfmt
    cargo
    clojure    # =clj=
    visualvm   # JVM profiling tool
    maven
    go_bootstrap


    ## xmonad

    xorg.xmodmap
    trayer
    dmenu
    escrotum
    xorg.xbacklight
    networkmanagerapplet
    playerctl
    lightdm
    fvwm                         # =xpmroot=
    haskellPackages.xmobar
    haskellPackages.yeganesh
    arandr



    ## GUI programs

    qemu
    thunderbird
    calibre
    quodlibet
    firefox
    emacs
    tdesktop
    vlc
    gnome3.evolution
    keepassx2-http
    yubioath-desktop
    tor-browser-bundle-bin
    transmission_gtk
    libreoffice
    android-studio
    androidsdk_extras
    androidndk

    ## Cryptocururencies

    electrum
    zbar          # for on-screen QR Code scanning
    monero

    ## nu specific packages
    slack
    chromium
  ];

  nixpkgs.config.allowUnfree = true; # Require for slack (unfree) derivation

  # Look at
  # https://www.vivaolinux.com.br/topico/Off-Code-Cafe/Me-apresente-sua-distro

  programs = {
    bash.enableCompletion = true;
  };

  services = {
    cron.enable = true;
    cron.systemCronJobs = ["* * * * * andreh mbsync -aV &>> /tmp/mbsync.log && notmuch new &>> /tmp/notmuch.log"];

    xserver = {
      enable = true;
      layout = "br";
      xkbOptions = "caps:swapescape";

      windowManager.default = "xmonad";
      windowManager.xmonad = {
        enable = true;
        enableContribAndExtras = true;
      };
      desktopManager = {
        default = "none";
        xterm.enable = false;
        gnome3.enable = true;
      };
      displayManager = {
        lightdm.enable = true;

        # The config inception was inspired by:
        # http://ubuntuforum-br.org/index.php?topic=13784.0
        # Lambda symbol name taken from:
        # http://wiki.linuxquestions.org/wiki/List_of_Keysyms_Recognised_by_Xmodmap
        # To test a keycode:
        # xmodmap -e 'keycode 118 = bar Greek_lamda'
        sessionCommands = ''
          ${pkgs.haskellPackages.xmobar}/bin/xmobar ~/.xmobarrc &
          ${pkgs.fvwm}/bin/xpmroot ~/Nextcloud/Images/emotion.png &
        '';
      };
    };

    gnome3 = {
      gnome-keyring.enable = true;
      seahorse.enable = true;
      gnome-terminal-server.enable = true;
      gpaste.enable = true;                # clipboard manager
      tracker.enable = true;
      sushi.enable = true;                 # nautilus previewer
      gnome-online-accounts.enable = true;
      gnome-documents.enable = true;
      evolution-data-server.enable = true;
      gvfs.enable = true;
    };

    pcscd.enable = true;                   # required by yubioath
  };

  security = {
    pam.services.lightdm.enableGnomeKeyring = true;
    sudo.enable = true;
  };

  users = {
    mutableUsers = false;

    extraUsers =
      let
        andrehUser =  {
          andreh = {
            isNormalUser = true;
            uid = 1000;
            description = "EuAndreh";
            extraGroups = [ "wheel" "networkmanager" "docker" ];
            passwordFile = "/home/andreh/annex/dev/code/dotfiles/encrypted/password-hash.txt";
          };
        };
        # From the Guix manual:
        # https://www.gnu.org/software/guix/manual/en/html_node/Build-Environment-Setup.html#Build-Environment-Setup
        buildUser = (i:
          {
            "guixbuilder${i}" = {                   # guixbuilder$i
              group = "guixbuild";                  # -g guixbuild
              extraGroups = ["guixbuild"];          # -G guixbuild
              home = "/var/empty";                  # -d /var/empty
              shell = pkgs.nologin;                 # -s `which nologin`
              description = "Guix build user ${i}"; # -c "Guix buid user $i"
              isSystemUser = true;                  # --system
            };
          }
        );
      in
        # merge all users
        pkgs.lib.fold (str: acc: acc // buildUser str)
                      andrehUser
                      # for i in `seq -w 1 10`
                      (map (pkgs.lib.fixedWidthNumber 2) (builtins.genList (n: n+1) 10));

    extraGroups.guixbuild = {
      name = "guixbuild";
    };
  };

  systemd = {
    services = {
      # Derived from Guix guix-daemon.service.in
      # https://git.savannah.gnu.org/cgit/guix.git/tree/etc/guix-daemon.service.in?id=00c86a888488b16ce30634d3a3a9d871ed6734a2
      guix-daemon = {
        enable = true;
        description = "Build daemon for GNU Guix";
        serviceConfig = {
          ExecStart = "/var/guix/profiles/per-user/root/guix-profile/bin/guix-daemon --build-users-group=guixbuild";
          Environment="GUIX_LOCPATH=/root/.guix-profile/lib/locale";
          RemainAfterExit="yes";
          StandardOutput="syslog";
          StandardError="syslog";
          TaskMax= "8192";
        };
        wantedBy = [ "multi-user.target" ];
      };
    };
  };

  # This value determines the NixOS release with which your system is to be
  # compatible, in order to avoid breaking some software such as database
  # servers. You should change this only after NixOS release notes say you
  # should.
  system.stateVersion = "18.03"; # Did you read the comment?
}