# Fork of [[User:Psiĥedelisto/VisualEditor ref namer.py]]
#
# (C) Pywikibot team, 2006-2021
#
# Distributed under the terms of the MIT license.
#
import mwparserfromhell
from mwparserfromhell.wikicode import Wikicode
import re
import sys
import pywikibot
from pywikibot import pagegenerators
from pywikibot.bot import (
    AutomaticTWSummaryBot,
    ConfigParserBot,
    ExistingPageBot,
    NoRedirectPageBot,
    SingleSiteBot,
)
# This is required for the text that is shown when you run this script
# with the parameter -help.
docuReplacements = {'&params;': pagegenerators.parameterHelp}  # noqa: N816
class BasicBot(
    # Refer pywikobot.bot for generic bot classes
    SingleSiteBot,  # A bot only working on one site
    ConfigParserBot,  # A bot which reads options from scripts.ini setting file
    # CurrentPageBot,  # Sets 'current_page'. Process it in treat_page method.
    #                  # Not needed here because we have subclasses
    ExistingPageBot,  # CurrentPageBot which only treats existing pages
    NoRedirectPageBot,  # CurrentPageBot which only treats non-redirects
    AutomaticTWSummaryBot,  # Automatically defines summary; needs summary_key
):
    """
    An incomplete sample bot.
    :ivar summary_key: Edit summary message key. The message that should be
        used is placed on /i18n subdirectory. The file containing these
        messages should have the same name as the caller script (i.e. basic.py
        in this case). Use summary_key to set a default edit summary message.
    :type summary_key: str
    """
    summary_key = 'basic-changing'
    update_options = {
        'replace': False,  # delete old text and write the new text
        'summary': "Cleaning up [[WP:VE|VisualEditor]] reference names",  # your own bot summary
        'text': None,  # add this text from option. 'Test' is default
        'top': False,  # append text on top of the page
    }
    def treat_page(self) -> None:
        """Load the given page, do some changes, and save it."""
        text = self.current_page.text
        # Taken from [[User:Psiĥedelisto/VisualEditor ref namer.py]]
        skip = True
        parsed = mwparserfromhell.parse( text )
        tags = list(filter(None, [t if t.has("name") else None for t in parsed.ifilter(forcetype=mwparserfromhell.wikicode.Tag, matches="<\\s*ref\\s*", recursive=True)]))

        refs = list(filter(lambda s: re.search("^:\d+$", str(s.get("name").value)) and not re.search("/>$", str(s)), tags))

        pretty = dict()

        for ref in refs:
            template = ref.contents.get(0)

            if template.has("vauthors"):
                v = str(template.get("vauthors").value)
            elif template.has("authors"):
                v = str(template.get("authors").value)
            elif template.has("last"):
                v = str(template.get("last").value)
            else:
                continue

            v = v.strip()

            if "," in v:
                last = v[:v.index(",")]
            elif " " in v:
                last = v[:v.index(" ")]
            else:
                last = v

            if template.has("date"):
                date = str(template.get("date").value)
            elif template.has("year"):
                date = str(template.get("year").value)

            date = re.search("\d{4}", date)[0]

            pretty[str(ref.get("name").value)] = "{}{}".format(last, date)

        for tag in parsed.ifilter(forcetype=mwparserfromhell.wikicode.Tag, matches="<\\s*ref\\s*", recursive=True):
            if not tag.has("name"): continue
            k = str(tag.get("name").value)
            if k in pretty:
                tag.attributes[0].value = pretty[k]
                skip = False # Don't skip if there are non-cosmetic changes

        for template in parsed.ifilter_templates():
            tn = template.name.strip()
            if tn.lower() == "rp" or tn.lower() == "ill" or tn.lower() == "lang" or tn.lower().startswith("lang-") or tn.lower() == "respell" or tn.lower() == "abbr":
                template.name = tn[0].lower()+tn[1:]
            else:
                template.name = tn[0].upper()+tn[1:]
            print(tn, "⇒", template.name, file=sys.stderr)

        # print(parsed)

        for k,v in pretty.items():
            print(k, "⇒", v, file=sys.stderr)

        if len(set(pretty)) == len(pretty):
            print("All replacements unique", file=sys.stderr)
        if not skip:
            text = parsed
        # if summary option is None, it takes the default i18n summary from
        # i18n subdirectory with summary_key as summary key.
        self.put_current(text, summary=self.opt.summary)
def main(*args: str) -> None:
    """
    Process command line arguments and invoke bot.
    If args is an empty list, sys.argv is used.
    :param args: command line arguments
    """
    options = {}
    # Process global arguments to determine desired site
    local_args = pywikibot.handle_args(args)
    # This factory is responsible for processing command line arguments
    # that are also used by other scripts and that determine on which pages
    # to work on.
    gen_factory = pagegenerators.GeneratorFactory()
    # Process pagegenerators arguments
    local_args = gen_factory.handle_args(local_args)
    # Parse your own command line arguments
    for arg in local_args:
        arg, sep, value = arg.partition(':')
        option = arg[1:]
        if option in ('summary', 'text'):
            if not value:
                pywikibot.input('Please enter a value for ' + arg)
            options[option] = value
        # take the remaining options as booleans.
        # You will get a hint if they aren't pre-defined in your bot class
        else:
            options[option] = True
    # The preloading option is responsible for downloading multiple
    # pages from the wiki simultaneously.
    gen = gen_factory.getCombinedGenerator(preload=True)
    if gen:
        # pass generator and private options to the bot
        bot = BasicBot(generator=gen, **options)
        bot.run()  # guess what it does
    else:
        pywikibot.bot.suggest_help(missing_generator=True)
if __name__ == '__main__':
    main()