# -*- coding: utf-8 -*-

import os.path
import re

from outwiker.api.core.text import readTextFile, writeTextFile

from .exporterfactory import ExporterFactory
from .indexgenerator import IndexGenerator


class BranchExporter:
    def __init__(self, startpage, nameGenerator, application):
        self.__startpage = startpage
        self.__application = application

        self.__indexfname = "__index.html"
        self.__contentfname = "__content.html"

        # Список ошибок, возникших при экспорте
        self.__log = []
        self.__nameGenerator = nameGenerator

        self.__a_tag_regex = re.compile(
            r"""
            (<\s*a\s+
            (.*?)
            href\s*=['"](.*?)['"]
            (.*?)>)
            """,
            re.IGNORECASE | re.MULTILINE | re.DOTALL | re.VERBOSE,
        )

        # Словарь, который сохраняет, как была названа каждая страница при экспорте
        # Ключ - страница, значение - имя ее директории или файла (без расширения) после экспорта
        self.__renames = {}

    @property
    def log(self):
        return self.__log

    def export(self, outdir, imagesonly, alwaysOverwrite):
        self.__log = []
        self.__renames = {}

        self.__export(
            self.__startpage, self.__startpage, outdir, imagesonly, alwaysOverwrite
        )

        self.__replacePageLinks(outdir)
        try:
            self.__createIndex(outdir, alwaysOverwrite)
        except IOError as e:
            self.log.append(str(e))

        return self.log

    def __createIndex(self, outdir, alwaysOverwrite):
        """
        Создать оглавление
        """
        indexpath = os.path.join(outdir, self.__indexfname)
        contentpath = os.path.join(outdir, self.__contentfname)

        indexgenerator = IndexGenerator(self.__startpage, self.__renames)
        indexgenerator.generatefiles(indexpath, contentpath)

    def __replacePageLinks(self, outdir):
        """
        Скорректировать ссылки на страницы
        """
        for page in list(self.__renames.keys()):
            fullname = os.path.join(outdir, self.__renames[page] + ".html")

            try:
                text = readTextFile(fullname)
                newtext = self.__replacePageLinksInText(text, page, outdir)
                writeTextFile(fullname, newtext)
            except BaseException as error:
                self.__log.append("{0}: {1}".format(page.title, str(error)))

    def __replacePageLinksInText(self, text, page, outdir):
        matches = self.__a_tag_regex.findall(text)
        hrefMatchIndex = 2
        fullMatchIndex = 0

        result = text

        for match in matches:
            url = match[hrefMatchIndex]
            if not url:
                continue

            # Проверить, что это не ссылка на сайт
            if self.__isInternetUrl(url):
                continue

            # Проверить, что это не ссылка на файл
            if self.__isFileLink(url, outdir):
                continue

            linkToPage = None
            anchor = None

            linkToPage, anchor = self.__getPageByProtocol(url)

            # Это ссылка на подстраницу?
            if linkToPage is None:
                linkToPage = page[url]

            if linkToPage is None:
                # Это ссылка на страницу из корня?
                correcturl = url[1:] if url[0] == "/" else url
                linkToPage = page.root[correcturl]

            if linkToPage is None:
                continue

            if linkToPage not in list(self.__renames.keys()):
                continue

            # Эта страница нам подходит
            # Новая ссылка
            newhref = self.__renames[linkToPage] + ".html"
            if anchor is not None:
                newhref += anchor

            newFullLink = match[fullMatchIndex].replace(url, newhref)

            result = result.replace(match[fullMatchIndex], newFullLink)

        return result

    def __getPageByProtocol(self, href):
        """
               Если href - протокол вида page://..., то возвращает страницу,
        на которую ведет ссылка (если она существует),
        в противном случае возвращает None.
        """
        protocol = "page://"

        if not href.startswith(protocol):
            return (None, None)

        # Отсечем протокол
        uid = href[len(protocol) :]

        # Отсечем все, что после /
        slashPos = uid.find("/")
        uid_clean = uid[:slashPos] if slashPos != -1 else uid

        page = self.__application.wikiroot.getPageByUid(uid_clean)
        anchor = self.__getAnchor(uid)

        return (page, anchor)

    def __getAnchor(self, href):
        """
        Попытаться найти якорь, если используется ссылка вида page://...
        """
        pos = href.rfind("/#")
        if pos != -1:
            return href[pos + 1 :]

        return None

    def __isInternetUrl(self, url):
        return (
            url.startswith("http://")
            or url.startswith("https://")
            or url.startswith("ftp://")
            or url.startswith("mailto:")
        )

    def __isFileLink(self, url, outdir):
        fname = os.path.join(outdir, url)
        return os.path.exists(fname) and os.path.isfile(fname)

    def __export(self, page, root, outdir, imagesonly, alwaysOverwrite):
        """
        page - страница, начиная с которой надо начать экспортирование
        root - корневая страница, откуда началось общее экспортирование (для определения имени файлов)
        outdir - директория для экспорта
        imagesonly - из вложений оставлять только картинки?
        alwaysOverwrite - перезаписывать существующие файлы?
        """
        if page.getTypeString() != "document":
            try:
                exporter = ExporterFactory.getExporter(page)
                exportname = self.__nameGenerator.getName(page)
                self.__renames[page] = exportname

                exporter.export(outdir, exportname, imagesonly, alwaysOverwrite)
            except BaseException as error:
                self.__log.append("{0}: {1}".format(page.title, str(error)))

        for child in page.children:
            self.__export(child, root, outdir, imagesonly, alwaysOverwrite)
