#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu

import os
import sys

from docopt import docopt
from path import Path as path

from gutenbergtozim import VERSION, logger
from gutenbergtozim.checkdeps import check_dependencies
from gutenbergtozim.database import setup_database
from gutenbergtozim.download import download_all_books
from gutenbergtozim.rdf import parse_and_fill, download_rdf_file, get_rdf_fpath
from gutenbergtozim.s3 import s3_credentials_ok
from gutenbergtozim.urls import setup_urls
from gutenbergtozim.zim import build_zimfile

help = (
    """Usage: gutenberg2zim [-y] [-F] [-l LANGS] [-f FORMATS] """
    """[-d CACHE_PATH] [-e STATIC_PATH] """
    """[-z ZIM_PATH] [-u RDF_URL] [-b BOOKS] """
    """[-t ZIM_TITLE] [-n ZIM_DESC] """
    """[-c CONCURRENCY] [--dlc CONCURRENCY] [--no-index] """
    """[--prepare] [--parse] [--download] [--export] [--dev] """
    """[--zim] [--complete] [-m ONE_LANG_ONE_ZIM_FOLDER] """
    """[--title-search] [--bookshelves] [--optimization-cache S3URL] """
    """[--stats-filename STATS_FILENAME]"""
    """

-h --help                       Display this help message
-y --wipe-db                    Empty cached book metadata
-F --force                      Redo step even if target already exist

-l --languages=<list>           Comma-separated list of lang codes to filter"""
    """ export to (preferably ISO 639-1, else ISO 639-3)
-f --formats=<list>             Comma-separated list of formats to filter """
    """export to (epub, html, pdf, all)

-e --static-folder=<folder>     Use-as/Write-to this folder static HTML
-z --zim-file=<file>            Write ZIM into this file path
-t --zim-title=<title>          Set ZIM title
-n --zim-desc=<description>     Set ZIM description
-d --dl-folder=<folder>         Folder to use/write-to downloaded ebooks
-u --rdf-url=<url>              Alternative rdf-files.tar.bz2 URL
-b --books=<ids>                Execute the processes for specific books, """
    """separated by commas, or dashes for intervals
-c --concurrency=<nb>           Number of concurrent process for processing """
    """tasks
--dlc=<nb>                      Number of concurrent *download* process for """
    """download (overwrites --concurrency). """
    """if server blocks high rate requests
-m --one-language-one-zim=<folder> When more than 1 language, do one zim for each """
    """language (and one with all)
--no-index                      Do NOT create full-text index within ZIM file
--check                         Check dependencies
--prepare                       Download rdf-files.tar.bz2
--parse                         Parse all RDF files and fill-up the DB
--download                      Download ebooks based on filters
--zim                           Create a ZIM file
--title-search                  Add field to search a book by title and directly """
    """jump to it
--bookshelves                   Add bookshelves
--optimization-cache=<url>      URL with credentials to S3 bucket for using as """
    """optimization cache
--use-any-optimized-version     Try to use any optimized version found on """
    """optimization cache
--stats-filename=<filename>  Path to store the progress JSON file to

This script is used to produce a ZIM file (and any intermediate state)
of Gutenberg repository using a mirror."""
)


def main(arguments):
    # optimizer version to use
    OPTIMIZER_VERSION = {"html": "v1", "epub": "v1", "cover": "v1"}

    # actions constants
    DO_PREPARE = arguments.get("--prepare", False)
    DO_PARSE = arguments.get("--parse", False)
    DO_DOWNLOAD = arguments.get("--download", False)
    DO_ZIM = arguments.get("--zim", False)
    DO_CHECKDEPS = arguments.get("--check", False)
    ONE_LANG_ONE_ZIM_FOLDER = arguments.get("--one-language-one-zim") or None
    COMPLETE_DUMP = arguments.get("--complete", False)

    ZIM_NAME = arguments.get("--zim-file")
    WIPE_DB = arguments.get("--wipe-db") or False
    RDF_URL = (
        arguments.get("--rdf-url")
        or "http://www.gutenberg.org/cache/epub/feeds/rdf-files.tar.bz2"
    )
    DL_CACHE = arguments.get("--dl-folder") or os.path.join("dl-cache")
    BOOKS = arguments.get("--books") or ""
    ZIM_TITLE = arguments.get("--zim-title")
    ZIM_DESC = arguments.get("--zim-desc")
    CONCURRENCY = int(arguments.get("--concurrency") or 16)
    DL_CONCURRENCY = int(arguments.get("--dlc") or CONCURRENCY)
    FORCE = arguments.get("--force", False)
    TITLE_SEARCH = arguments.get("--title-search", False)
    BOOKSHELVES = arguments.get("--bookshelves", False)
    OPTIMIZATION_CACHE = arguments.get("--optimization-cache") or None
    USE_ANY_OPTIMIZED_VERSION = arguments.get("--use-any-optimized-version", False)
    STATS_FILENAME = arguments.get("--stats-filename") or None

    s3_storage = None
    if OPTIMIZATION_CACHE:
        s3_storage = s3_credentials_ok(OPTIMIZATION_CACHE)
        if not s3_storage:
            raise ValueError("Unable to connect to Optimization Cache. Check its URL.")
        logger.info("S3 Credentials OK. Continuing ... ")

    # create tmp dir
    path("tmp").mkdir_p()

    LANGUAGES = [
        x.strip().lower()
        for x in (arguments.get("--languages") or "").split(",")
        if x.strip()
    ]
    # special shortcuts for "all"
    if arguments.get("--formats") in ["all", None]:
        FORMATS = ["epub", "pdf", "html"]
    else:
        FORMATS = list(
            set(
                [
                    x.strip().lower()
                    for x in (arguments.get("--formats") or "").split(",")
                    if x.strip()
                ]
            )
        )

    try:
        BOOKS = [bid for bid in BOOKS.split(",")]

        def f(x):
            return list(map(int, [i for i in x.split("-") if i.isdigit()]))

        books = []
        for i in BOOKS:
            blst = f(i)
            if len(blst) > 1:
                blst = range(blst[0], blst[1] + 1)
            books.extend(blst)
        BOOKS = list(set(books))
    except Exception as e:
        logger.error(e)
        BOOKS = []

    # no arguments, default to --complete
    if not (DO_PREPARE + DO_PARSE + DO_DOWNLOAD + DO_ZIM):
        COMPLETE_DUMP = True

    if COMPLETE_DUMP:
        DO_CHECKDEPS = DO_PREPARE = DO_PARSE = DO_DOWNLOAD = DO_ZIM = True

    if DO_CHECKDEPS:
        logger.info("CHECKING for dependencies on the system")
        if not check_dependencies()[0]:
            logger.error("Exiting...")
            sys.exit(1)

    rdf_path = get_rdf_fpath()

    if DO_PREPARE:
        logger.info("PREPARING rdf-files cache from {}".format(RDF_URL))
        download_rdf_file(rdf_url=RDF_URL, rdf_path=rdf_path)

    if WIPE_DB:
        logger.info("RESETING DATABASE IF EXISTS")
    logger.info("SETTING UP DATABASE")
    setup_database(wipe=WIPE_DB)

    if DO_PARSE:
        logger.info("PARSING rdf-files in {}".format(rdf_path))
        parse_and_fill(rdf_path=rdf_path, only_books=BOOKS, force=FORCE)
        logger.info("Add possible url to db")
        setup_urls(force=FORCE)

    if DO_DOWNLOAD:
        logger.info("DOWNLOADING ebooks from mirror using filters")
        download_all_books(
            download_cache=DL_CACHE,
            concurrency=DL_CONCURRENCY,
            languages=LANGUAGES,
            formats=FORMATS,
            only_books=BOOKS,
            force=FORCE,
            s3_storage=s3_storage,
            optimizer_version=OPTIMIZER_VERSION
            if not USE_ANY_OPTIMIZED_VERSION
            else None,
        )
    if ONE_LANG_ONE_ZIM_FOLDER:
        if LANGUAGES == []:
            zims = []
            from gutenbergtozim.database import Book

            for book in Book.select(Book.language).distinct():
                zims.append([book.language])
            zims.append([])
        else:
            zims = [[lang] for lang in LANGUAGES] + [LANGUAGES]
    else:
        zims = [LANGUAGES]

    for zim_lang in zims:

        if DO_ZIM:

            logger.info("BUILDING ZIM dynamically")
            build_zimfile(
                output_folder=path(ONE_LANG_ONE_ZIM_FOLDER or ".").abspath(),
                download_cache=DL_CACHE,
                concurrency=CONCURRENCY,
                languages=zim_lang,
                formats=FORMATS,
                only_books=BOOKS,
                force=FORCE,
                title_search=TITLE_SEARCH,
                add_bookshelves=BOOKSHELVES,
                s3_storage=s3_storage,
                optimizer_version=OPTIMIZER_VERSION,
                zim_name=path(ZIM_NAME).name if ZIM_NAME else None,
                title=ZIM_TITLE,
                description=ZIM_DESC,
                stats_filename=STATS_FILENAME,
            )


if __name__ == "__main__":
    main(docopt(help, version=VERSION))
