import argparse
import logging
import logging.config
import sys
import configparser

from os.path import isfile

from .mysql import UbacMysql
from .rsync import UbacRsync
from .filesystem import UbacFs
from .postgresql import UbacPostgresql
from .docker import UbacDocker
from .destination import SshDestination, FtpDestination
from . import logger, parse_list


DEFAULT_CONFIG_FILENAME = '/etc/ubac/ubac.ini'


class Runner(object):
    def __init__(self, config_file=None, check=False):
        self.config_file = config_file
        self.check = check

        self.remotes = {}
        self.chains = {}

        if config_file:
            self.read_config(config_file)
        else:
            self.read_config(DEFAULT_CONFIG_FILENAME)

    def read_config(self, filename):
        if not isfile(filename):
            raise FileNotFoundError(
                'Config file %s does not exists' % (filename)
            )
        config = configparser.SafeConfigParser()
        config.read([filename])

        logging_conf = config.get('ubac', 'logging_conf')
        if logging_conf:
            logging.config.fileConfig(logging_conf)

        remote_names = parse_list(config.get('ubac', 'remotes'))
        for remote_name in remote_names:
            section = config['ubac:'+remote_name]
            if section['type'] == 'ftp':
                remote_class = FtpDestination
            elif section['type'] == 'ssh':
                remote_class = SshDestination
            else:
                raise ValueError(
                    'unknown type %s for section %s',
                    section['type'],
                    'ubac:' + remote_name
                )
            remote = remote_class.from_section(section)
            self.remotes[remote_name] = remote

        chain_names = parse_list(config.get('ubac', 'chains'))
        for chain_name in chain_names:
            section = config['ubac:' + chain_name]
            if section['type'] == 'fs':
                chain_class = UbacFs
            elif section['type'] == 'mysql':
                chain_class = UbacMysql
            elif section['type'] == 'pg':
                chain_class = UbacPostgresql
            elif section['type'] == 'rsync':
                chain_class = UbacRsync
            elif section['type'] == 'docker':
                chain_class = UbacDocker
            else:
                raise ValueError(
                    'unknown type %s for section %s',
                    section['type'],
                    'ubac:'+chain_name
                )
            remote = self.remotes[section['remote']]
            chain = chain_class.from_section(section, remote)
            self.chains[chain_name] = chain

    def run(self):
        all_ok = True
        for chain in self.chains.values():
            try:
                if self.check:
                    this_status = chain.check_all()
                else:
                    this_status = chain.backup_all()
                all_ok = all_ok and this_status
            except KeyboardInterrupt:
                return -1
            except:
                logger.exception(
                    'Error backuping %s', chain.__class__
                )
                all_ok = False

        return not all_ok and 1 or 0


def main():
    parser = argparse.ArgumentParser(description='Backup some data')
    parser.add_argument(
        '--config', dest="config", help="Read configuration from that file",
        default=''
    )
    parser.add_argument(
        '--check', dest='check', action="store_true",
        help='Just launch a check on made backups'
    )

    args, remaining_argv = parser.parse_known_args()
    runner = Runner(args.config, args.check)
    sys.exit(runner.run())
