#! /usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright © 2016, IOhannes m zmölnig, IEM

# This file is part of virtshaus
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iaem-downloader. If not, see <http://www.gnu.org/licenses/>.

# tasks:
# - read a .ini file with host specifications
# - run virtshaus-lvmback for each host (or for all)

OPTION_OUTPUTDIR = "outdir"  # the output directory
OPTION_AUTOMATIC = "auto"  # whether to automatically guess config
OPTION_PARTITIONS = "partitions"  # enumeration of partitions to backup
OPTION_ADDTIME = "timestamp"  # whether to add a timestamp to the output
OPTION_VERBOSE = "verbosity"  # level of verbosity (can be negative)
OPTION_DEBUG = "debug"  # debug level
OPTION_ENCRYPT = "encrypt"  # if set, the encryption key
OPTION_COMPRESS = "compress"  # if set, the compression method

compression_methods = {
    "gzip": "-z",
    "zip": "-Z",
    "compress": "-Z",
    "bzip": "-j",
    "bzip2": "-j",
    "xzip": "-J",
    "": "-z",  # default
}


def getOptions(config, host):
    options = []
    if not config.has_section(host):
        return options
    config = config[host]

    # for x in config.keys(): print("[%s:%s] %s" % (host, x, config.get(x)))

    if OPTION_OUTPUTDIR not in config:
        return options

    verbosity = None
    try:
        verbosity = config.getint(OPTION_VERBOSE)
    except ValueError:
        pass
    if verbosity:
        options += ["-q" for _ in range(-verbosity)]
        options += ["-v" for _ in range(verbosity)]

    debuglevel = None
    try:
        debuglevel = config.getint(OPTION_DEBUG)
    except ValueError:
        pass
    if debuglevel:
        options += ["-d" for _ in range(debuglevel)]

    zipflag = None
    try:
        if config.getboolean(OPTION_COMPRESS):
            zipflag = compression_methods[""]
    except ValueError:
        compressor = config.get(OPTION_COMPRESS)
        try:
            zipflag = compression_methods[compressor.lower()]
        except KeyError:
            pass
    if zipflag:
        options += [zipflag]

    if OPTION_ENCRYPT in config:
        options += ["-e", config.get(OPTION_ENCRYPT)]

    try:
        if config.getboolean(OPTION_AUTOMATIC):
            options += ["-A"]
    except ValueError:
        pass

    try:
        if config.getboolean(OPTION_ADDTIME):
            options += ["-T"]
    except ValueError:
        pass

    if OPTION_OUTPUTDIR in config:
        options += ["-o", config.get(OPTION_OUTPUTDIR)]

    options += ["-n", host]
    if OPTION_PARTITIONS in config:
        partitionstring = config.get(OPTION_PARTITIONS)
        options += partitionstring.split()

    return options


def getConfig(configfile):
    import configparser
    import collections

    class SectionBasicInterpolation(configparser.BasicInterpolation):
        def before_get(self, parser, section, option, value, defaults):
            defaults = collections.ChainMap(*defaults.maps + [{"section": section}])
            return super().before_get(parser, section, option, value, defaults)

    config = configparser.ConfigParser(interpolation=SectionBasicInterpolation())
    config.read(configfile)
    return config


def parseCmdlineArgs():
    import argparse

    parser = argparse.ArgumentParser()
    DEFAULT_CONFIGFILE = "/etc/virtshaus/backup/hosts.cfg"
    parser.add_argument(
        "-c", "--config", type=str, help="configfile [DEFAULT: %s]" % DEFAULT_CONFIGFILE
    )
    parser.add_argument(
        "-n",
        "--dry-run",
        action="store_true",
        help="just print the cmdlines (don't do anything)",
    )
    parser.add_argument("hosts", nargs="*", help="hosts to backup [DEFAULT: <ALL>]")

    args = parser.parse_args()
    if not args.config:
        args.config = DEFAULT_CONFIGFILE
    return args


def runCmd(options, dry=False):
    import subprocess

    cmd = ["/usr/sbin/virtshaus-lvmbackup"]
    cmd += options
    if dry:
        cmd.insert(0, "echo")
    subprocess.call(cmd)


if __name__ == "__main__":
    args = parseCmdlineArgs()
    cfg = getConfig(args.config)
    if not args.hosts:
        args.hosts = cfg.sections()
    for host in args.hosts:
        opt = getOptions(cfg, host)
        runCmd(opt, args.dry_run)
