{ config, lib, pkgs, ... }:

with lib;

let

  cfg = config.programs.vim;
  defaultPlugins = [ "sensible" ];

in

{
  options = {
    programs.vim = {
      enable = mkEnableOption "Vim";

      lineNumbers = mkOption {
        type = types.nullOr types.bool;
        default = null;
        description = "Whether to show line numbers.";
      };

      tabSize = mkOption {
        type = types.nullOr types.int;
        default = null; 
        example = 4;
        description = "Set tab size and shift width to a specified number of spaces.";
      };

      plugins = mkOption {
        type = types.listOf types.str;
        default = defaultPlugins;
        example = [ "YankRing" ];
        description = ''
          List of vim plugins to install.
          For supported plugins see: https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/vim-plugin-names
        '';
      };

      extraConfig = mkOption {
        type = types.lines;
        default = "";
        example = ''
          set nocompatible
          set nobackup
        '';
        description = "Custom .vimrc lines";
      };

      package = mkOption {
        type = types.package;
        description = "Resulting customized vim package";
        readOnly = true;
      };
    };
  };

  config = (
    let
      optionalBoolean = name: val: optionalString (val != null) (if val then "set ${name}" else "unset ${name}");
      optionalInteger = name: val: optionalString (val != null) "set ${name}=${toString val}";
      customRC = ''
        ${optionalBoolean "number" cfg.lineNumbers}
        ${optionalInteger "tabstop" cfg.tabSize}
        ${optionalInteger "shiftwidth" cfg.tabSize}

        ${cfg.extraConfig}
      '';

      vim = pkgs.vim_configurable.customize {
        name = "vim";
        vimrcConfig.customRC = customRC;
        vimrcConfig.vam.knownPlugins = pkgs.vimPlugins;
        vimrcConfig.vam.pluginDictionaries = [
          { names = defaultPlugins ++ cfg.plugins; }
        ];
      };

    in mkIf cfg.enable {
      programs.vim.package = vim;
      home.packages = [ cfg.package ];
    }
  );
}