#!/usr/bin/env python3
# coding: utf-8

# created: 05.05.20

"""
Welcome to the 'luechenbresse' module initialization script.

Usage:
    luechenbresse [--info] [--init] [--dir DIR] [--get FEED] [--get_all]
    luechenbresse --version
    luechenbresse (-h | --help)

Options
    -h --help           Show this screen
    --version           print program version
    --tatsch            produces a file in the scripts current working directory (test only)
    --info              print some info about environment
    --args              print parsed command line arguments (test only)
    --init              initialize local structures in ~/.luechenbresse
    --dir DIR           folder for the database files, relative to CWD, you better use ~/...
                        if not specified, ~/.luechenbresse will be used
                        caveat: existing settings will be overwritten when specified
    --get FEED          gets a certain feed from the internet
    --get_all           gets all feeds from the internet

The optional "--dir" command line argument is only used when "--init" is also specified.
All housekeeping commands use the database folder specified in ~/.luechenbresse/luechenbresse.ini.
"""

import sys
import os
from time import time
import json
from pathlib import Path
import configparser
import tracemalloc
import sqlite3
import logging
import logging.handlers

from docopt import docopt

from luechenbresse import data
from luechenbresse.feed import process_feed, process_all_feeds
from luechenbresse import ini
from luechenbresse.mailgun import Mailgun

# cwd ist der Aufrufort (Skript muss nicht ausführbar i.S.v. `chmod u+x` sein)
# Files aus der Distribution können über die `__files__` Variable navogiert werden.

def info(args):
    logging.info("I am", os.environ['_'])
    logging.info(f"Running under {sys.executable} ({sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro})")
    logging.info(f"Current Working Directory: {os.getcwd()}")
    logging.info(f"__file__ = {__file__}")
    feeds = data.feeds()
    logging.info(f"feeds: {type(feeds)}, {json.dumps(feeds)}")
    Mailgun().shoot("luechenbresse --info", "Hey there.")

def create_db(db_file, schema):
    # TODO support more than one schema per db
    if isinstance(schema, list):
        schema = schema[0]
    sql, _ = data.schema(schema)
    con = sqlite3.connect(db_file)
    cur = con.cursor()
    cur.executescript(sql)
    con.close()

def init(db_folder):
    # TODO move to module

    # create ~/.luechenbresse
    config_folder = Path(os.environ["HOME"]) / ".luechenbresse"
    logging.info(f"Configuration folder: {config_folder}", end=" ")
    if config_folder.exists():
        logging.info(f"Configuration folder: {config_folder} OK")
    else:
        logging.info(f"Configuration folder: {config_folder} will be created")
        config_folder.mkdir()

    # create init-file
    ini_file = config_folder / "luechenbresse.ini"
    config = configparser.ConfigParser()
    if ini_file.exists():
        logging.info(f"Configuration file: {ini_file} OK")
    else:
        logging.info(f"Configuration file: {ini_file} will be created")
        ini_file.touch()

    config.read(ini_file)
    if not config.has_section("databases"):
        config.add_section("databases")

    # create database folder
    if not db_folder:
        db_folder = config_folder
        logging.info("Databases go into default location")
    else:
        db_folder = Path(db_folder).resolve()
        logging.info(f"Databases go into {db_folder}")

    if "folder" in config["databases"]:
        current_db_folder = config["databases"]["folder"]
        logging.info(f"Current folder for databases: {current_db_folder} - will be replaced")
    else:
        logging.info("No database location specified yet")

    logging.info(f"Setting database location to {db_folder}")
    config["databases"]["folder"] = str(db_folder)
    with open(ini_file, "w") as fp:
        config.write(fp)

    if db_folder.exists():
        logging.info("Using existing folder")
    else:
        logging.info(f"Creating {db_folder}...")
        db_folder.mkdir()

    feeds = data.feeds()
    for name in feeds:
        logging.info(f"Installing {name}")
        feed = feeds[name]
        db_file = db_folder / feed["db"]
        schema = feed["schema"]
        if db_file.exists():
            logging.info(f"Database {db_file} exists. LEAVING UNCHANGED")
        else:
            logging.info(f"Database {db_file} will be created with schema {schema}")
            # TODO: buffer schema
            create_db(db_file, schema)

def get(name):
    process_feed(name)

def get_all():
    process_all_feeds()

def setup_logging():
    # TODO optional config for logging in luechenbresse.ini
    log_file = Path(os.environ["HOME"]) / ".luechenbresse" / "default.log"
    rfh = logging.handlers.RotatingFileHandler(log_file, maxBytes=100_000, backupCount=10)
    rfh.setLevel(logging.INFO)
    sh = logging.StreamHandler(sys.stdout)
    sh.setLevel(logging.DEBUG)
    fmt = "%(asctime)s [%(levelname)s] %(message)s"
    logging.basicConfig(level=logging.INFO, handlers=[ rfh, sh ], format=fmt)

if __name__ == "__main__":
    tracemalloc.start()
    t0 = time()
    setup_logging()
    logging.info("Willkommen bei der Luechenbresse.")

    try:
        arguments = docopt(__doc__, version='Luechenbresse 0.0.2')
        logging.info(f"cli: {json.dumps(arguments)}")
        done = False

        if arguments["--info"]:
            info(arguments)
            raise SystemExit(0)
    #        done = True

        if arguments["--init"]:
            init(arguments["--dir"])
            done = True

        if arguments["--get"]:
            get(arguments["--get"])
            done = True

        if arguments["--get_all"]:
            get_all()
            done = True

        if not done:
            logging.warning("Was wolltest Du denn?")

        logging.info("Time total: %0.1fs" % (time() - t0))
        current, peak = tracemalloc.get_traced_memory()
        logging.info("Memory: current = %0.1f MB, peak = %0.1f MB" % (current / 1024.0 / 1024, peak / 1024.0 / 1024))
    except KeyboardInterrupt:
        logging.warning("caught KeyboardInterrupt")
    except Exception as ex:
        logging.exception("Sorry.")
    logging.info("Ciao.")