#! /usr/bin/env python3

"""
Usage:
    prefixspan-cli (frequent | top-k) <threshold> [options] [<file>]

    prefixspan-cli --help


Options:
    --closed           Return only closed patterns.

    --key=<key>        Custom key function. [default: ]
                       Must be a Python function in form of "lambda patt, matches: ...", returning a float value.
                       Returns a float value.
    --bound=<bound>    The upper-bound function of the respective key function. [default: ]
                       When unspecified, the same key function is used.
                       Must be a Python function in form of "lambda patt, matches: ...", returning a float value.
                       Must be no less than the key function, i.e. bound(patt, matches) ≥ key(patt, matches).
                       Must be anti-monotone, i.e. for patt1 ⊑ patt2, bound(patt1, matches1) ≥ bound(patt2, matches2).

    --filter=<filter>  Custom filter function. [default: ]
                       Must be a Python function in form of "lambda patt, matches: ...", returning a boolean value.

    --minlen=<minlen>  Minimum length of patterns. [default: 1]
    --maxlen=<maxlen>  Maximum length of patterns. [default: 1000]
"""

from typing import *

import sys
from functools import partial

from docopt import docopt

from prefixspan import PrefixSpan

print2 = partial(print, file=sys.stderr)

def checkArg(arg, cond):
    # type: (str, Callable[[int], bool]) -> int
    try:
        val = int(argv[arg])
        if not cond(val):
            raise ValueError
    except ValueError:
        print2("ERROR: Cannot parse {}.".format(arg))
        print2(__doc__)
        sys.exit(1)

    return val


def checkFunc(arg):
    # type: (str) -> Callable[..., bool]
    try:
        return eval(argv[arg])
    except:
        print2("ERROR: Cannot parse {}.".format(arg))
        print2(__doc__)
        sys.exit(1)


if __name__ == "__main__":
    argv = docopt(__doc__)

    ps = PrefixSpan([
        [int(v) for v in line.rstrip().split(' ')]
        for line in (open(argv["<file>"]) if argv["<file>"] else sys.stdin)
    ])

    func = ps.frequent if argv["frequent"] else ps.topk

    key = checkFunc("--key") if argv["--key"] else None
    bound = checkFunc("--bound") if argv["--bound"] else key

    threshold = checkArg("<threshold>", lambda v: key is not None or v > 0)

    closed = argv["--closed"]

    filter = checkFunc("--filter") if argv["--filter"] else None

    if argv["--minlen"]:
        ps.minlen = checkArg("--minlen", lambda v: v > 0)
    if argv["--maxlen"]:
        ps.maxlen = checkArg("--maxlen", lambda v: v >= ps.minlen)

    for freq, patt in func(
            threshold, closed=closed,
            key=key, bound=bound,
            filter=filter
        ):
        print("{} : {}".format(' '.join(str(v) for v in patt), freq))
