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

import os
import sys

import pkg_resources
import click
import yaml

from . import bdt
from ..build import parse_dependencies, conda_create, make_conda_config
from ..constants import BASE_CONDARC, CONDA_BUILD_CONFIG, \
    CONDA_RECIPE_APPEND, SERVER
from ..bootstrap import set_environment, get_channels

from ..log import verbosity_option, get_logger, echo_normal
logger = get_logger(__name__)


@click.command(epilog='''
Examples:

  1. Creates an environment called `myenv' for developing the currently checked-out package (N.B.: first activate the base environment):

\b
     $ cd bob.package.foo
     $ bdt create -vv myenv

     The above command assumes the directory `conda' exists on the current directory and that it contains a file called `meta.yaml' containing the recipe for the package you want to create a development environment for.

     If you get things right by default, the above form is the typical usage scenario of this app. Read-on to tweak special flags and settings.


  2. By default, we use the native python version of your conda installation as the default python version to use for the newly created environment. You may select a different one with `--python=X.Y':

     $ bdt create -vv --python=3.6 myenv


  3. By default, we use our own condarc and `conda_build_config.yaml` files that are used in creating packages for our CI/CD system. If you wish to use your own, specify them on the command line:

     $ bdt create -vv --python=3.6 --config=config.yaml --condarc=~/.condarc myenv

     Notice the condarc file **must** end in `condarc', or conda will complain.


  4. You can use the option `--dry-run' to simulate what would be installed
  instead of actually creating a new environment.  Combine with `-vvv` to
  enable debug printing.  Equivalent conda commands you can execute on the
  shell will be printed:


     $ bdt create -vvv --dry-run myenv
''')
@click.argument('name')
@click.argument('recipe-dir', required=False, type=click.Path(file_okay=False,
  dir_okay=True, exists=True))
@click.option('-p', '--python', default=('%d.%d' % sys.version_info[:2]),
    show_default=True, help='Version of python to build the ' \
        'environment for [default: %(default)s]')
@click.option('-o', '--overwrite/--no-overwrite', default=False,
      help='If set and an environment with the same name exists, ' \
          'deletes it first before creating the new environment',
          show_default=True)
@click.option('-r', '--condarc',
    help='Use custom conda configuration file instead of our own',)
@click.option('-l', '--use-local', default=False,
    help='Allow the use of local channels for package retrieval')
@click.option('-m', '--config', '--variant-config-files', show_default=True,
      default=CONDA_BUILD_CONFIG, help='overwrites the path leading to ' \
          'variant configuration file to use')
@click.option('-a', '--append-file', show_default=True,
      default=CONDA_RECIPE_APPEND, help='overwrites the path leading to ' \
          'appended configuration file to use')
@click.option('-S', '--server', show_default=True, default=SERVER,
    help='Server used for downloading conda packages and documentation ' \
        'indexes of required packages')
@click.option('-g', '--group', show_default=True, default='bob',
    help='Group of packages (gitlab namespace) this package belongs to')
@click.option('-P', '--private/--no-private', default=False,
    help='Set this to **include** private channels on your build - ' \
        'you **must** be at Idiap to execute this build in this case - ' \
        'you **must** also use the correct server name through --server - ' \
        'notice this option has no effect if you also pass --condarc')
@click.option('-X', '--stable/--no-stable', default=False,
    help='Set this to **exclude** beta channels from your build - ' \
        'notice this option has no effect if you also pass --condarc')
@click.option('-d', '--dry-run/--no-dry-run', default=False,
    help='Only goes through the actions, but does not execute them ' \
        '(combine with the verbosity flags - e.g. ``-vvv``) to enable ' \
        'printing to help you understand what will be done')
@verbosity_option()
@bdt.raise_on_error
def create(name, recipe_dir, python, overwrite, condarc, use_local, config,
    append_file, server, group, private, stable, dry_run):
  """Creates a development environment for a recipe

  It uses the conda render API to render a recipe and install an environment
  containing all build/host, run and test dependencies of a package. It does
  **not** build the package itself, just install dependencies so you can build
  the package by hand, possibly using buildout or similar. If you'd like to
  conda-build your package, just use `conda build` instead.

  Once the environment is created, a copy of the used `condarc' file is placed
  on the root of the environment. Installing or updating packages on the newly
  created environment should be possible without further configuration. Notice
  that beta packages quickly get outdated and upgrading may no longer be
  possible for aging development environments. You're advised to always re-use
  this app and use the flag `--overwrite` to re-create from scratch the
  development environment.
  """

  recipe_dir = recipe_dir or os.path.join(os.path.realpath('.'), 'conda')

  if not os.path.exists(recipe_dir):
    raise RuntimeError("The directory %s does not exist" % recipe_dir)

  # this is not used to conda-build, just to create the final environment
  conda = os.environ.get('CONDA_EXE')
  if conda is None:
    raise RuntimeError("Cannot find `conda' executable (${CONDA_EXEC}) - " \
        "have you activated the build environment containing bob.devtools " \
        "properly?")

  # set some environment variables before continuing
  set_environment('DOCSERVER', server, os.environ)

  logger.debug('This package is considered part of group "%s" - tunning ' \
      'conda package URLs for this...', group)

  if condarc is not None:
    logger.info('Loading CONDARC file from %s...', condarc)
    with open(condarc, 'rb') as f:
      condarc_options = yaml.load(f, Loader=yaml.FullLoader)
  else:
    # use default and add channels
    condarc_options = yaml.load(BASE_CONDARC, Loader=yaml.FullLoader)
    channels = get_channels(public=(not private), stable=stable, server=server,
        intranet=private, group=group)
    condarc_options['channels'] = channels + ['defaults']

  conda_config = make_conda_config(config, python, append_file, condarc_options)
  deps = parse_dependencies(recipe_dir, conda_config)
  status = conda_create(conda, name, overwrite, condarc_options, deps,
      dry_run, use_local)
  echo_normal('Execute on your shell: "conda activate %s"' % name)