import json
import logging

import click

import rasterio


@click.command(short_help="Sample a dataset.")
@click.argument('files', nargs=-1, required=True, metavar='FILE "[x, y]"')
@click.option('-b', '--bidx', default=None, help="Indexes of input file bands.")
@click.pass_context
def sample(ctx, files, bidx):
    """Sample a dataset at one or more points

    Sampling points (x, y) encoded as JSON arrays, in the coordinate
    reference system of the dataset, are read from the second
    positional argument or stdin. Values of the dataset's bands
    are also encoded as JSON arrays and are written to stdout.

    Example:

    \b
        $ cat << EOF | rio sample tests/data/RGB.byte.tif
        > [220650, 2719200]
        > [219650, 2718200]
        > EOF
        [28, 29, 27]
        [25, 29, 19]

    By default, rio-sample will sample all bands. Optionally, bands
    may be specified using a simple syntax:

      --bidx N samples the Nth band (first band is 1).

      --bidx M,N,0 samples bands M, N, and O.

      --bidx M..O samples bands M-O, inclusive.

      --bidx ..N samples all bands up to and including N.

      --bidx N.. samples all bands from N to the end.

    Example:

    \b
        $ cat << EOF | rio sample tests/data/RGB.byte.tif --bidx ..2
        > [220650, 2719200]
        > [219650, 2718200]
        > EOF
        [28, 29]
        [25, 29]

    """
    verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
    logger = logging.getLogger('rio')

    files = list(files)
    source = files.pop(0)
    input = files.pop(0) if files else '-'

    # Handle the case of file, stream, or string input.
    try:
        points = click.open_file(input).readlines()
    except IOError:
        points = [input]

    try:
        with rasterio.Env(CPL_DEBUG=verbosity > 2):
            with rasterio.open(source) as src:
                if bidx is None:
                    indexes = src.indexes
                elif '..' in bidx:
                    start, stop = map(
                        lambda x: int(x) if x else None, bidx.split('..'))
                    if start is None:
                        start = 1
                    indexes = src.indexes[slice(start - 1, stop)]
                else:
                    indexes = list(map(int, bidx.split(',')))
                for vals in src.sample(
                        (json.loads(line) for line in points), indexes=indexes):
                    click.echo(json.dumps(vals.tolist()))

    except Exception:
        logger.exception("Exception caught during processing")
        raise click.Abort()
