#!python
import logging
import os

from logging import handlers

import click

import nearuplib
from nearuplib.constants import LOGS_FOLDER
from nearuplib.localnet import entry
from nearuplib.nodelib import restart_nearup, setup_and_run, stop_nearup
from nearuplib.tailer import show_logs

if not os.path.exists(LOGS_FOLDER):
    os.makedirs(LOGS_FOLDER)

logging.basicConfig(
    level=logging.INFO,
    format=
    '%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
    handlers=[
        handlers.RotatingFileHandler(
            os.path.expanduser('~/.nearup/logs/nearup.log'),
            maxBytes=1024 * 1024,
            backupCount=10,
        ),
        logging.StreamHandler()
    ],
)


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


@cli.command()
@click.argument('network',
                type=click.Choice(
                    {'mainnet', 'testnet', 'betanet', 'crashnet', 'localnet'}))
@click.option(
    '--binary-path',
    type=str,
    default='',
    help=
    'Near binary path, use nearcore/target/debug or nearcore/target/release for local development'
)
@click.option(
    '--home',
    type=str,
    help=
    'Home path for storing configs, keys and chain data (Default: ~/.near/testnet)'
)
@click.option('--account-id', type=str, help='Specify the node account ID')
@click.option('--boot-nodes',
              type=str,
              help='Specify the nodes to boot from',
              default='')
@click.option(
    '--verbose',
    is_flag=True,
    help='If set, prints verbose logs. Betanet always prints verbose logs.')
@click.option(
    '--neard-log',
    type=str,
    help='Comma-separated module=level values passed to neard --verbose flag',
    default='')
@click.option('--num-nodes',
              type=int,
              help='Specifies the number of localnet nodes to create',
              default=4)
@click.option('--num-shards',
              type=int,
              help='Specifies the number of localnet shards to create',
              default=1)
@click.option('--override',
              is_flag=True,
              help='Override previous localnet node data if exists')
@click.option('--no-watcher',
              is_flag=True,
              help='Disable nearup watcher, mostly used for tests.')
def run(network, binary_path, home, account_id, boot_nodes, verbose, neard_log,
        num_nodes, num_shards, override, no_watcher):
    if home:
        home = os.path.abspath(home)
    else:
        home = os.path.expanduser(f'~/.near/{network}')

    logging.info(f"Home directory is {home}...")

    if network == 'betanet':
        verbose = True

    if network == 'localnet':
        entry(binary_path, home, num_nodes, num_shards, override, verbose)
    else:
        init_flags = [f'--chain-id={network}']
        if account_id:
            init_flags.append(f'--account-id={account_id}')

        setup_and_run(binary_path,
                      home,
                      init_flags,
                      boot_nodes,
                      verbose=verbose,
                      neard_log=neard_log,
                      watcher=not no_watcher)


@click.option('--keep-watcher', is_flag=True, help='Keep the watcher running.')
@cli.command()
def stop(keep_watcher):
    stop_nearup(keep_watcher)


@click.argument('network',
                type=click.Choice(
                    {'testnet', 'betanet', 'crashnet', 'localnet'}))
@click.option(
    '--home',
    type=str,
    help=
    'Home path for storing configs, keys and chain data (Default: ~/.near/testnet)'
)
@click.option('--restart-watcher',
              is_flag=True,
              help='Restart the watcher as well')
@cli.command()
def restart(network, home, restart_watcher):
    if home:
        home = os.path.abspath(home)
    else:
        home = os.path.expanduser(f'~/.near/{network}')

    restart_nearup(network, home_dir=home, keep_watcher=not restart_watcher)


@click.option('--follow', '-f', is_flag=True, help='Follow the logs.')
@click.option('--lines', '-l', default=100, type=int)
@cli.command()
def logs(follow, lines):
    show_logs(follow, lines)


@cli.command()
def version():
    version_path = os.path.join(os.path.dirname(nearuplib.__file__), 'VERSION')
    with open(version_path, 'r') as version_file:
        print(version_file.read().strip())


if __name__ == '__main__':
    cli()
