#!/usr/bin/env python3

# Unit tests for decopy
# Copyright: 2018, Maximiliano Curia <maxy@debian.org>
#
# License: ISC
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#  .
#  THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
#  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
#  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  PERFORMANCE OF THIS SOFTWARE.

import json
import sys
import time
from pathlib import Path

try:
    from tqdm import tqdm
except ImportError:

    def tqdm(*a, **kw):  # type: ignore[no-redef]
        if a:
            return a[0]
        return kw.get("iterable")


from decopy.common.re_types import ReSub, ReSubGroup
from decopy.licensing import holders, license_subs, licenses


class SpeedCheck:
    def run(self):
        self.benchmark_licenses_res()
        self.benchmark_clean_comments()
        self.benchmark_copyright()
        self.benchmark_resubs()
        return 0

    def load_all_licenses(self):
        texts = []
        for filename in Path().glob("tests/testdata/licenses/*.json"):
            with filename.open() as file_:
                license_ = json.load(file_)
            for key in ("licenseText", "standardLicenseHeader", "licenseExceptionText"):
                if key not in license_:
                    continue
                texts.append(license_[key])
        return texts

    def benchmark_licenses_res(self):
        texts = self.load_all_licenses()
        times = []

        for i, pattern in tqdm(
            enumerate(licenses.COMPILED_RES),
            desc="Timing license res",
            total=len(licenses.COMPILED_RES),
            dynamic_ncols=True,
        ):
            start = time.time()
            for text in texts:
                pattern.search(text)
            elapsed = time.time() - start
            times.append((elapsed, i))

        base, amount = 0, 0
        interesting = times[base : base + amount]
        if interesting:
            print(
                "Sum of current selection: ",
                sum(elapsed for elapsed, _ in interesting),
            )
        times.sort()

        for elapsed, i in [times[0], *interesting, *times[-5:]]:
            license_re = licenses.LICENSES_RES[i]
            print(
                f"Time for {i} ({license_re.license}): {elapsed}\n{license_re.re}",
            )

    def benchmark_resubs(self):
        texts = self.load_all_licenses()
        times: list[tuple[float, int | tuple[int, int]]] = []
        resubs = (
            license_subs.ARTISTIC_SUBS
            + license_subs.BSD_SUBS
            + license_subs.CC_BY_SUBS
            + license_subs.CECILL_SUBS
            + license_subs.CNRI_SUBS
            + license_subs.EFL_SUBS
            + license_subs.GNU_VERSION_SUBS
            + license_subs.GNU_EXCEPTION_SUBS
            + license_subs.GFDL_SUBS
            + license_subs.LPPL_SUBS
            + license_subs.MIT_SUBS
            + license_subs.ZPL_SUBS
        )

        for i, resub in tqdm(
            enumerate(resubs),
            desc="Timing resubs",
            total=len(resubs),
            dynamic_ncols=True,
        ):
            if isinstance(resub, ReSubGroup):
                for j, regroupsub in enumerate(resub.subs):
                    start = time.time()
                    for text in texts:
                        regroupsub.pattern.subn(regroupsub.repl, text, 1)
                    elapsed = time.time() - start
                    times.append((elapsed, (i, j)))
            else:
                start = time.time()
                for text in texts:
                    resub.pattern.subn(resub.repl, text, 1)
                elapsed = time.time() - start
                times.append((elapsed, i))

        base, amount = 0, 0
        interesting = times[base : base + amount]
        if interesting:
            print(
                "Sum of current selection: ",
                sum(elapsed for elapsed, _ in interesting),
            )
        times.sort()

        for elapsed, indexes in [times[0], *interesting, *times[-5:]]:
            if isinstance(indexes, tuple):
                group = resubs[indexes[0]]
                assert isinstance(group, ReSubGroup)
                resub = group.subs[indexes[1]]
            else:
                resub = resubs[indexes]
            if not isinstance(resub, ReSub):
                print(f"W: Not a ReSub {indexes}")
                print(f"Time for {indexes} (repl: {resub}): {elapsed}")
                continue
            print(f"Time for {indexes} (repl: {resub.repl}): {elapsed}")

    def benchmark_clean_comments(self):
        texts = self.load_all_licenses()
        times = []

        for i, sub in tqdm(
            enumerate(licenses.COMMENTS_SUBS),
            desc="Timing comment res",
            total=len(licenses.COMMENTS_SUBS),
            dynamic_ncols=True,
        ):
            start = time.time()
            for text in texts:
                sub.pattern.sub(sub.repl, text)
            elapsed = time.time() - start
            times.append((elapsed, i))

        base, amount = 0, 0
        interesting = times[base : base + amount]
        if interesting:
            print(
                "Sum of current selection: ",
                sum(elapsed for elapsed, _ in interesting),
            )
        times.sort()

        for elapsed, i in [times[0], *interesting, *times[-5:]]:
            print(f"Time for {i} : {elapsed}")

    def benchmark_copyright(self):
        texts = self.load_all_licenses()
        times = []

        patterns = (
            holders.COPYRIGHT_PRE_IGNORE_RES
            + holders.COPYRIGHT_POST_IGNORE_RES
            + (holders.COPYRIGHT_PRE_INDICATOR_RE, holders.COPYRIGHT_INDICATOR_RE)
        )

        for i, pattern in tqdm(
            enumerate(patterns),
            desc="Timing copyright res",
            total=len(patterns),
            dynamic_ncols=True,
        ):
            start = time.time()
            for text in texts:
                pattern.findall(text)
            elapsed = time.time() - start
            times.append((elapsed, i))

        base, amount = 0, 0
        # len(licenses.COPYRIGHT_PRE_IGNORE_RES) + 1, \
        #     len(licenses.COPYRIGHT_POST_IGNORE_RES)
        interesting = times[base : base + amount]
        if interesting:
            print(
                "Sum of current selection: ",
                sum(elapsed for elapsed, _ in interesting),
            )
        times.sort()

        for elapsed, i in [times[0], *interesting, *times[-5:]]:
            print(f"Time for {i} : {elapsed}")


if __name__ == "__main__":
    check = SpeedCheck()
    sys.exit(check.run())
