#! /usr/bin/env python3
"""Show some lines from files"""

import os
import re
import sys

from pysyte import args as arguments
from pysyte import text_streams


def parse_args():
    """Parse out command line arguments"""
    parser = arguments.parser(__doc__)
    parser.args('files', help='files to edit')
    parser.int('-a', '--at', default=None, help='Show line at the line number')
    parser.true('-p', '--paste', help='Paste text from clipboard')
    parser.true('-i', '--stdin', help='Wait for text from stdin')
    parser.arg('-f', '--first', default="1",
               help='number/regexp of first line to show')
    parser.arg('-l', '--last', default="0",
               help='number/regexp of last line to show')
    parser.true('-n', '--numbers', help='Show line numbers')
    parser.int('-w', '--width', help='Max width of shown line')
    return parser.parse_args()


def parse_lines(args, lines_read):

    def as_int(string, start):
        try:
            return int(string)
        except (ValueError, TypeError):
            matcher = re.compile(string)
            for i, line in enumerate(lines_read, 1):
                if i <= start:
                    continue
                if matcher.search(line):
                    return i
        return 0

    def _line(i):
        line = i if i >= 0 else length_read + 1 + i
        if line >= length_read:
            return length_read
        return 0 if line < 1 else line

    def _boundaries():
        if not args.at:
            first = _line(as_int(args.first, 0) - 1)
            last = _line(as_int(args.last, first) or -1)
            return first, last
        first = _line(args.at)
        return first, first + 1

    length_read = len(lines_read)
    first, last = _boundaries()
    lines = [] if first > length_read else lines_read[first:last]
    return lines, first


def line_format(lines):
    """A string format for line numbers

    Should give a '%d' format with width bug enough to accomodate the last line
    """
    last_line_number = len(lines)
    digits = len(str(last_line_number))
    return '%%%dd: ' % digits


def show_stream(stream, args):
    text = stream.read()
    lines_in = text.splitlines()
    lines, first = parse_lines(args, lines_in)
    line_format_ = line_format(lines)
    for i, line in enumerate(lines, first):
        if args.numbers:
            prefix = line_format_ % (i + 1)
            out = ' '.join((prefix, line.rstrip()))
        else:
            out = line.rstrip()
        if args.width:
            out = out[:args.width]
        print(out)


def main():
    """Run the script"""
    args = parse_args()
    streams = text_streams.args(args, 'files')
    for stream in streams:
        show_stream(stream, args)
    return os.EX_OK


if __name__ == '__main__':
    sys.exit(main())
