__author__ = "Huu Hoa NGUYEN (huuhoa@gmail.com)"
__version__ = "0.3.0"
__copyright__ = "Copyright (c) 2020 Huu Hoa NGUYEN"
# Use of this source code is governed by the MIT license.
__license__ = "MIT"


import json
import os
import pathlib

from bs4 import BeautifulSoup

from colusa.etr import ContentNotFoundError, Render, create_extractor, create_transformer


def create_book_maker(config: dict):
    return Render(config)


class ConfigurationError(Exception):
    def __init__(self, reason: str):
        self.reason = reason

    def __str__(self):
        return f'ConfigurationError: {self.reason}'


class Colusa(object):
    def __init__(self, configuration: dict):
        from colusa.utils import scan
        scan('colusa.plugins')
        self.config = configuration
        self.output_dir = configuration.get('output_dir', '.')
        self.book_maker = create_book_maker(configuration)

    @classmethod
    def generate_new_configuration(cls, file_path):
        template = {
                "title": "__fill the title__",
                "author": "__fill the author__",
                "version": "v1.0",
                "homepage": "__fill url to home page__",
                "output_dir": "__fill output dir__",
                "multi_part": False,
                "parts": [],
                "urls": []
            }
        with open(file_path, 'w') as file_out:
            json.dump(template, file_out, indent=4)

    def download_content(self, url_path):
        from .utils import download_url, get_hexdigest

        output_path = pathlib.Path(self.output_dir)
        cached_file_path = output_path.joinpath('.cached', f'{get_hexdigest(url_path)}.html')
        p = pathlib.PurePath(url_path)
        print(url_path, p.name, cached_file_path)

        if not cached_file_path.exists():
            # download file from url_path
            download_url(url_path, str(cached_file_path))

        with open(cached_file_path, 'rt', encoding='utf-8') as file_in:
            content = file_in.read()
        return content, p.name

    def ebook_generate_content(self, url_path):
        content, file_basename = self.download_content(url_path)
        bs = BeautifulSoup(content, 'html.parser')

        try:
            extractor = create_extractor(url_path, bs)
            extractor.cleanup()
            transformer = create_transformer(url_path, extractor.get_content(), self.output_dir)
            transformer.transform()
            self.book_maker.render_chapter(extractor, transformer, url_path, file_basename)
        except ContentNotFoundError as e:
            print(e, url_path)
            # raise e

    def generate(self):
        os.makedirs(os.path.join(self.output_dir, ".cached"), exist_ok=True)
        os.makedirs(os.path.join(self.output_dir, "images"), exist_ok=True)
        self.book_maker.generate_makefile()

        multi_part = self.config.get('multi_part', False)
        if multi_part:
            self._generate_book_multi_part()
        else:
            self._generate_book_single_part()

        self.book_maker.ebook_generate_master_file()

    def _generate_book_single_part(self):
        paths = self.config.get('urls', [])
        if len(paths) == 0:
            raise ConfigurationError('urls field must contain at least one url')
        for url_path in paths:
            self.ebook_generate_content(url_path)

    def _generate_book_multi_part(self):
        parts = self.config.get('parts', [])
        if len(parts) == 0:
            raise ConfigurationError('parts field must contain at least one part object')
        for part in parts:
            self.book_maker.render_book_part(part['title'], part.get('description', ''))
            urls = part.get('urls', [])
            for url_path in urls:
                self.ebook_generate_content(url_path)


def read_configuration_file(file_path):
    with open(file_path, 'r') as file_in:
        data = json.load(file_in)
        return data

