# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

from __future__ import annotations

import configparser
import dataclasses
import io
import re
from typing import TYPE_CHECKING

from recipe_engine import recipe_api

if TYPE_CHECKING:  # pragma: no cover
    from typing import Generator
    from recipe_engine import config_types
    from RECIPE_MODULES.pigweed.checkout import api as checkout_api
    from RECIPE_MODULES.pigweed.roll_util import api as roll_util_api


@dataclasses.dataclass
class Submodule:
    path: str
    name: str
    branch: str
    remote: str = dataclasses.field(default=None)
    dir: config_types.Path = dataclasses.field(default=None)


@dataclasses.dataclass
class RevisionChange:
    old: str
    new: str


class SubmoduleRollApi(recipe_api.RecipeApi):

    Submodule = Submodule
    RevisionChange = RevisionChange

    def update_pin(
        self,
        checkout: checkout_api.CheckoutContext,
        path: config_types.Path,
        new_revision: str,
    ) -> RevisionChange:
        with self.m.context(cwd=checkout.top):
            self.m.git.submodule_update(
                paths=(path,),
                timeout=checkout.options.submodule_timeout_sec,
            )

        old_revision = self.m.checkout.get_revision(
            path, 'get old revision', test_data='1' * 40
        )

        with self.m.context(cwd=path):
            self.m.git('git fetch', 'fetch', 'origin', new_revision)
            self.m.git('git checkout', 'checkout', 'FETCH_HEAD')

        # In case new_revision is a branch name we need to retrieve the hash it
        # resolved to.
        if not re.search(r'^[0-9a-f]{40}$', new_revision):
            new_revision = self.m.checkout.get_revision(
                path, 'get new revision', test_data='2' * 40
            )

        return RevisionChange(old=old_revision, new=new_revision)

    def update(
        self,
        checkout: checkout_api.CheckoutContext,
        submodule_entries: Sequence[SubmoduleEntry],
    ) -> dict[config_types.Path, roll_util_api.Roll]:
        # Confirm the given path is actually a submodule.
        gitmodules = self.m.file.read_text(
            'read .gitmodules', checkout.root / '.gitmodules'
        )
        # Example .gitmodules file:
        # [submodule "third_party/pigweed"]
        #   path = third_party/pigweed
        #   url = https://pigweed.googlesource.com/pigweed/pigweed

        # configparser doesn't like leading whitespace on lines, despite what its
        # documentation says.
        gitmodules = re.sub(r'\n\s+', '\n', gitmodules)
        parser = configparser.RawConfigParser()
        parser.readfp(io.StringIO(gitmodules))

        rolls: dict[config_types.Path, self.m.roll_util.Roll] = {}

        for entry in submodule_entries:
            submodule = Submodule(
                path=entry.path,
                name=entry.name or entry.path,
                branch=entry.branch,
            )
            submodule.dir = checkout.root / submodule.path

            with self.m.step.nest(submodule.name) as pres:
                section = f'submodule "{submodule.name}"'
                if not parser.has_section(section):
                    sections = parser.sections()
                    submodules = sorted(
                        re.sub(r'^.*"(.*)"$', r'\1', x) for x in sections
                    )
                    raise self.m.step.StepFailure(
                        'no submodule "{}" (submodules: {})'.format(
                            submodule.name,
                            ', '.join('"{}"'.format(x) for x in submodules),
                        )
                    )

                if not submodule.branch:
                    try:
                        submodule.branch = parser.get(section, 'branch')
                    except configparser.NoOptionError:
                        submodule.branch = 'main'

                submodule.remote = self.m.roll_util.normalize_remote(
                    parser.get(section, 'url'),
                    checkout.options.remote,
                )

                new_revision = self.m.git_roll_util.resolve_new_revision(
                    submodule.remote,
                    submodule.branch,
                    checkout.remotes_equivalent,
                )

                change = self.update_pin(
                    checkout,
                    submodule.dir,
                    new_revision,
                )

                direction = self.m.roll_util.get_roll_direction(
                    submodule.dir, change.old, change.new
                )

                # If the primary roll is not necessary or is backwards we can
                # exit immediately and don't need to check deps.
                if self.m.roll_util.can_roll(direction):
                    rolls[submodule.path] = self.m.roll_util.create_roll(
                        project_name=str(submodule.path),
                        old_revision=change.old,
                        new_revision=change.new,
                        proj_dir=submodule.dir,
                        direction=direction,
                        nest_steps=False,
                    )

                else:
                    pres.step_summary_text = 'no roll required'
                    self.m.roll_util.skip_roll_step(
                        submodule.remote, change.old, change.new
                    )

        return rolls
