r'''shelephant_hostinfo
    Collect file information from location (on a remote host).

:usage:

    shelephant_hostinfo [options]

:options:

    -o, --output=N
        Output YAML-file. [default: shelephant_hostinfo.yaml].

    -r, --host=N
        Host-name.

    -p, --prefix=N
        Directory (on host) from which to copy.

    -f, --files=[N]
        YAML-file with list of files (on remote). [default: shelephant_dump.yaml]

    -c, --checksum=[N]
        YAML-file with checksums (on remote). [default: shelephant_checksum.yaml]

    --files-key=N
        Path in the YAML-file, separated by "/". [default: /]

    --checksum-key=N
        Path in the YAML-file, separated by "/". [default: /]

    --ignore
        Skip basic checks.

    -i, --input=[N]
        Use host and prefix from existing file. [default: shelephant_hostinfo.yaml]

    --remove=N...
        Remove paths (and checksums) from existing file.

    --force
        Overwrite output file without prompt.

    --verbose
        Verbose all commands.

    -h, --help
        Show help.

    --version
        Show version.


(c - MIT) T.W.J. de Geus | tom@geus.me | www.geus.me | github.com/tdegeus/shelephant
'''

import argparse
import os
import tempfile
import shutil
import numpy as np

from .. import version
from .. import YamlGetItem
from .. import YamlDump
from .. import YamlRead
from .. import CopyFromRemote


def remove(data, rm):

    files = np.array(data['files'])
    sorter = np.argsort(files)
    files = files[sorter]
    rm = np.sort(rm)

    test = np.in1d(rm, files)
    if not np.all(np.in1d(rm, files)):
        raise IOError('One or more remove paths not found')

    idx = np.searchsorted(files, rm)
    keep = np.setdiff1d(np.arange(len(files)), sorter[idx])

    files = data['files']
    checksum = data['checksum']
    data['files'] = [files[i] for i in keep]
    data['checksum'] = [checksum[i] for i in keep]

    return data


def main():

    try:

        # Parse command-line arguments

        class Parser(argparse.ArgumentParser):
            def print_help(self):
                print(__doc__)

        parser = Parser()
        parser.add_argument('-o', '--output', required=False, default='shelephant_hostinfo.yaml')
        parser.add_argument('-r', '--host', required=False, default=None)
        parser.add_argument('-p', '--prefix', required=False, default=None)
        parser.add_argument('-f', '--files', required=False, default=None, nargs='?', const='shelephant_dump.yaml')
        parser.add_argument('-c', '--checksum', required=False, default=None, nargs='?', const='shelephant_checksum.yaml')
        parser.add_argument(      '--files-key', required=False, default='/')
        parser.add_argument(      '--checksum-key', required=False, default='/')
        parser.add_argument(      '--ignore', required=False, action='store_true')
        parser.add_argument('-i', '--input', required=False, default=None, nargs='?', const='shelephant_hostinfo.yaml')
        parser.add_argument(      '--remove', required=False, nargs='*')
        parser.add_argument(      '--force', required=False, action='store_true')
        parser.add_argument(      '--verbose', required=False, action='store_true')
        parser.add_argument('-v', '--version', action='version', version=version)
        args = parser.parse_args()

        # Separate mode: remove paths and quit

        if args.remove:
            filename = args.output
            if args.input:
                filename = args.input
            data = YamlRead(filename)
            data = remove(data, args.remove)
            YamlDump(args.output, data, args.force)
            return 0

        # Extract basic information from command-line arguments

        data = {}

        if args.host:
            data['host'] = args.host

        if args.prefix:
            data['prefix'] = args.prefix

        if args.input:
            overwrite = YamlRead(args.input)
            for item in ['host', 'prefix']:
                if item in overwrite:
                    data[item] = overwrite[item]

        # Basic IO-checks

        if not args.ignore:
            if 'host' in data and 'prefix' not in data:
                raise IOError('Specify hostname and prefix')

        if 'host' not in data and 'prefix' not in data:
            for item in [args.files, args.checksum]:
                if item:
                    data['prefix'] = os.path.dirname(item)
                    break

        # Create temporary file to download to

        if 'host' in data:
            temp_dir = tempfile.mkdtemp()
            temp_file = os.path.join(temp_dir, 'shelephant_hostinfo.yaml')

        # Read files and checksums

        args_dict = vars(args)

        for item in ['files', 'checksum']:

            if args_dict[item]:

                key = list(filter(None, args_dict[item + '_key'].split('/')))
                filename = args_dict[item]

                if 'host' in data:
                    CopyFromRemote(
                        data['host'],
                        os.path.join(data['prefix'], filename),
                        temp_file,
                        args.verbose)
                    filename = temp_file

                data[item] = YamlGetItem(filename, key)

        # Run basic checks

        if not args.ignore:
            for item in ['prefix']:
                if item not in data:
                    raise IOError('Please specify {0:s}'.format(item))
            if 'checksum' in data:
                if len(data['files']) != len(data['checksum']):
                    raise IOError('Number of checksums does not match number of files')

        # Clean-up: remove temporary file

        if 'host' in data:
            shutil.rmtree(temp_dir)

        # Write output

        if 'files' not in data:
            data['files'] = []

        YamlDump(args.output, data, args.force)

    except Exception as e:

        print(e)
        return 1

if __name__ == '__main__':

    main()
