#!/usr/bin/env python

from __future__ import print_function

import callysto
import jupyter_client.kernelspec

import argparse
import importlib
import inspect
import json
import os, sys
import shutil
import tempfile

parser = argparse.ArgumentParser()

parser.add_argument("python_class",
    help = """(mandatory) fully qualified name of a Python class extending
    callysto.BaseKernel""")

parser.add_argument("--all-users",
    dest = "user_only", action = "store_false", default = True,
    help = "(optional) if set, will install the kernel for all users")

options = parser.parse_args()

def error (msg):
    print("error: %s" % msg, file = sys.stderr)
    sys.exit(1)

if (options.python_class.count('.') < 1):
    module_name, class_name = options.python_class, None
else:
    module_name, class_name = options.python_class.rsplit('.', 1)

try:
    kernel_module = importlib.import_module(module_name)
except ImportError as exception:
    if (str(exception).endswith(module_name)):
        error("invalid qualified name: module '%s' not found" % module_name)
    else:
        error("error while importing '%s': %s" % (module_name, exception))

def walk_classes (module):
    objects = inspect.getmembers(module, inspect.ismodule)
    while (len(objects) > 0):
        _, obj = objects.pop(0)
        if (inspect.isclass(obj)):
            yield obj
        else:
            objects.extend(inspect.getmembers(obj, inspect.isclass))

if (class_name is not None):
    try:
        kernel_class = getattr(kernel_module, class_name)
    except AttributeError:
        error("invalid qualified name: class '%s' not found" % class_name)

    if (not issubclass(kernel_class, callysto.BaseKernel)):
        error(
            "invalid class: '%s' is not a subclass "
            "of callysto.BaseKernel" % kernel_class)

else:
    kernel_class = None
    for candidate in walk_classes(kernel_module):
        if (issubclass(candidate, callysto.BaseKernel)):
            kernel_class = candidate
            break

    if (kernel_class is None):
        error(
            "invalid module '%s': no class subclassing "
            "callysto.BaseKernel found" % module_name)

kernel_class.install(all_users = not options.user_only)
print("Installed kernel: %s" % kernel_class)
