#!/usr/bin/env python
import click
import json
import os
import sys

import lakesuperior.env_setup

from lakesuperior.api import admin as admin_api
from lakesuperior.config_parser import config
from lakesuperior.globals import AppGlobals
from lakesuperior.env import env
from lakesuperior.store.ldp_rs.lmdb_store import TxnManager

rdfly = env.app_globals.rdfly
nonrdfly = env.app_globals.nonrdfly


@click.group()
def admin():
    pass

@click.command()
def bootstrap():
    '''
    Bootstrap binary and graph stores.

    This script will parse configuration files and initialize a filesystem and
    triplestore with an empty FCREPO repository.
    It is used in test suites and on a first run.

    Additional scaffolding files may be parsed to create initial contents.
    '''
    click.echo(
            click.style(
                'WARNING: This operation will WIPE ALL YOUR DATA.\n',
                bold=True, fg='red')
            + 'Are you sure? (Please type `yes` to continue) > ', nl=False)
    choice = input().lower()
    if choice != 'yes':
        click.echo('Aborting.')
        sys.exit(1)

    click.echo('Initializing graph store at {}'.format(rdfly.store.path))
    with TxnManager(env.app_globals.rdf_store, write=True) as txn:
        rdfly.bootstrap()
        rdfly.store.close()
    click.echo('Graph store initialized.')

    click.echo('Initializing binary store at {}'.format(nonrdfly.root))
    nonrdfly.bootstrap()
    click.echo('Binary store initialized.')
    click.echo('Repository successfully set up. Go to town.')


@click.command()
@click.option(
    '--human', '-h', is_flag=True, flag_value=True,
    help='Print a human-readable string. By default, JSON is printed.')
def stats(human=False):
    '''
    Print repository statistics.

    @param human (bool) Whether to output the data in human-readable
    format.
    '''
    stat_data = admin_api.stats()
    if human:
        click.echo(
            'This option is not supported yet. Sorry.\nUse the `/admin/stats`'
            ' endpoint in the web UI for a pretty printout.')
    else:
        click.echo(json.dumps(stat_data))


@click.command()
def check_fixity(uid):
    '''
    [STUB] Check fixity of a resource.
    '''
    pass


@click.command()
def check_refint():
    '''
    [STUB] Check referential integrity.

    This command scans the graph store to verify that all references to
    resources within the repository are effectively pointing to existing
    resources. For repositories set up with the `referencial_integrity` option
    (the default), this is a pre-condition for a consistent data set.
    '''
    pass


@click.command()
def cleanup():
    '''
    [STUB] Clean up orphan database items.
    '''
    pass


@click.command()
def copy():
    '''
    [STUB] Copy (backup) repository data.

    This s a low-level copy, which backs up the data directories containing
    graph and binary data. It may not even be a necessary command since to
    back up the repository one just needs to copy the binary and metadata
    folders.
    '''
    pass


@click.command()
@click.argument('src')
@click.argument('dest')
@click.option(
    '--binaries', '-b', show_default=True,
    help='If set to `include`, full binaries are included in the dump. If '
    'set to `truncate`, binaries are created as zero-byte files in the proper '
    'folder structure. If set to `skip`, binaries are not exported. Data '
    'folders are not created.')
def dump(src, dest, binaries='include'):
    '''
    [STUB] Dump repository to disk.

    Dump a Fedora 4 repository to disk. The Fedora repo can be
    LAKEsuperior or another compatible implementation.
    '''
    pass


@click.command()
@click.argument('src')
@click.argument('dest')
def load(src, dest):
    '''
    [STUB] Load serialized repository data.

    Load serialized data from a filesystem location into a Fedora repository.
    The Fedora repo can be LAKEsuperior or another compatible implementation.
    '''
    pass


admin.add_command(bootstrap)
admin.add_command(check_fixity)
admin.add_command(check_refint)
admin.add_command(cleanup)
admin.add_command(copy)
admin.add_command(dump)
admin.add_command(load)
admin.add_command(stats)

if __name__ == '__main__':
    admin()
