name: Get Conan Recipe Version

on:
    workflow_call:
        inputs:
            project_name:
                required: true
                type: string

            additional_buildmetadata:
                required: false
                default: ""
                type: string

        outputs:
            recipe_id_full:
                description: "The full Conan recipe id: <name>/<version>@<user>/<channel>"
                value: ${{ jobs.get-semver.outputs.recipe_id_full }}

            recipe_id_latest:
                description: "The full Conan recipe aliased (latest) id: <name>/(latest)@<user>/<channel>"
                value: ${{ jobs.get-semver.outputs.recipe_id_latest }}

            recipe_semver_full:
                description: "The full semver <Major>.<Minor>.<Patch>-<PreReleaseTag>+<BuildMetaData>"
                value: ${{ jobs.get-semver.outputs.semver_full }}

            is_release_branch:
                description: "is current branch a release branch?"
                value: ${{ jobs.get-semver.outputs.release_branch }}

            user:
                description: "The conan user"
                value: ${{ jobs.get-semver.outputs.user }}

            channel:
                description: "The conan channel"
                value: ${{ jobs.get-semver.outputs.channel }}

            project_name:
                description: "The conan projectname"
                value: ${{ inputs.project_name }}

jobs:
    get-semver:

        runs-on: ubuntu-latest

        outputs:
            recipe_id_full: ${{ steps.get-conan-broadcast-data.outputs.recipe_id_full }}
            recipe_id_latest: ${{ steps.get-conan-broadcast-data.outputs.recipe_id_latest }}
            semver_full: ${{ steps.get-conan-broadcast-data.outputs.semver_full }}
            is_release_branch: ${{ steps.get-conan-broadcast-data.outputs.is_release_branch }}
            user: ${{ steps.get-conan-broadcast-data.outputs.user }}
            channel: ${{ steps.get-conan-broadcast-data.outputs.channel }}

        steps:
            -   name: Checkout repo
                uses: actions/checkout@v3
                if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
                with:
                    fetch-depth: 0
                    ref: ${{ github.head_ref }}

            -   name: Checkout repo PR
                uses: actions/checkout@v3
                if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
                with:
                    fetch-depth: 0
                    ref: ${{ github.event.pull_request.head.ref }}
                    repository: ${{ github.event.pull_request.head.repo.full_name }}

            -   name: Setup Python and pip
                uses: actions/setup-python@v4
                with:
                    python-version: "3.10.x"
                    cache: 'pip'
                    cache-dependency-path: .github/workflows/requirements-conan-package.txt

            -   name: Install Python requirements and Create default Conan profile
                run: |
                    pip install -r .github/workflows/requirements-conan-package.txt
                    pip install gitpython

            -   id: get-conan-broadcast-data
                name: Get Conan broadcast data
                run: |
                    import subprocess
                    from conans import tools
                    from conans.errors import ConanException
                    from git import Repo
                    
                    repo = Repo('.')
                    user = "${{ github.repository_owner }}".lower()
                    project_name = "${{ inputs.project_name }}"
                    event_name = "${{ github.event_name }}"
                    issue_number = "${{ github.ref }}".split('/')[2]
                    is_tag = "${{ github.ref_type }}" == "tag"
                    is_release_branch = False
                    ref_name = "${{ github.base_ref }}" if event_name == "pull_request" else "${{ github.ref_name }}"
                    buildmetadata = "" if "${{ inputs.additional_buildmetadata }}" == "" else "${{ inputs.additional_buildmetadata }}_"
                    
                    # FIXME: for when we push a tag (such as an release)
                    channel = "testing"
                    if is_tag:
                        branch_version = tools.Version(ref_name)
                        is_release_branch = True
                        channel = "_"
                        user = "_"
                        actual_version = f"{branch_version}"
                    else:
                        try:
                            branch_version = tools.Version(repo.active_branch.name)
                        except ConanException:
                            branch_version = tools.Version('0.0.0')
                        if ref_name == f"{branch_version.major}.{branch_version.minor}":
                            channel = 'stable'
                            is_release_branch = True
                        elif ref_name in ("main", "master"):
                            channel = 'testing'
                        else:
                            channel = repo.active_branch.name.split("_")[0].replace("-", "_").lower()
                    
                        if "pull_request" in event_name:
                            channel = f"pr_{issue_number}"
                    
                        # %% Get the actual version
                        latest_branch_version = tools.Version("0.0.0")
                        latest_branch_tag = None
                        for tag in repo.git.tag(merged = True).splitlines():
                            if str(tag).startswith("firmware") or str(tag).startswith("master"):
                                continue  # Quick-fix for the versioning scheme name of the embedded team in fdm_materials(_private) repo
                            try:
                                version = tools.Version(tag)
                            except ConanException:
                                continue
                            if version > latest_branch_version:
                                latest_branch_version = version
                                latest_branch_tag = repo.tag(tag)
                        
                        if latest_branch_tag:
                            # %% Get the actual version
                            no_commits = 0
                            for commit in repo.iter_commits("HEAD"):
                                if commit == latest_branch_tag.commit:
                                    break
                                no_commits += 1
                            latest_branch_version_prerelease = latest_branch_version.prerelease
                            if latest_branch_version.prerelease and not "." in latest_branch_version.prerelease:
                                # The prerealese did not contain a version number, default it to 1
                                latest_branch_version_prerelease = f"{latest_branch_version.prerelease}.1"
                            if event_name == "pull_request":
                                actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version_prerelease.lower()}+{buildmetadata}pr_{issue_number}_{no_commits}"
                                channel_metadata = f"{channel}_{no_commits}"
                            else:
                                if channel in ("stable", "_", ""):
                                    channel_metadata = f"{no_commits}"
                                else:
                                    channel_metadata = f"{channel}_{no_commits}"
                            if is_release_branch:
                                if latest_branch_version.prerelease == "":
                                    # An actual full release has been created, we are working on patch
                                    bump_up_patch = int(latest_branch_version.patch) + 1
                                    actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{bump_up_patch}-beta.1+{buildmetadata}{channel_metadata}"
                                else:
                                    # An beta release has been created we are working toward a next beta or full release
                                    bump_up_release_tag = int(latest_branch_version.prerelease.split('.')[1]) + 1
                                    actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version.prerelease.split('.')[0]}.{bump_up_release_tag}+{buildmetadata}{channel_metadata}"
                            else:
                                bump_up_minor = int(latest_branch_version.minor) + 1
                                reset_patch = 0
                                actual_version = f"{latest_branch_version.major}.{bump_up_minor}.{reset_patch}-alpha+{buildmetadata}{channel_metadata}"

                    # %% print to output
                    cmd_name = ["echo", f"::set-output name=name::{project_name}"]
                    subprocess.call(cmd_name)
                    cmd_version = ["echo", f"::set-output name=version::{actual_version}"]
                    subprocess.call(cmd_version)
                    cmd_channel = ["echo", f"::set-output name=channel::{channel}"]
                    subprocess.call(cmd_channel)
                    cmd_id_full= ["echo", f"::set-output name=recipe_id_full::{project_name}/{actual_version}@{user}/{channel}"]
                    subprocess.call(cmd_id_full)
                    cmd_id_latest = ["echo", f"::set-output name=recipe_id_latest::{project_name}/latest@{user}/{channel}"]
                    subprocess.call(cmd_id_latest)
                    cmd_semver_full = ["echo", f"::set-output name=semver_full::{actual_version}"]
                    subprocess.call(cmd_semver_full)
                    cmd_is_release_branch = ["echo", f"::set-output name=is_release_branch::{str(is_release_branch).lower()}"]
                    subprocess.call(cmd_is_release_branch)
                    
                    print("::group::Conan Recipe Information")
                    print(f"name = {project_name}")
                    print(f"version = {actual_version}")
                    print(f"user = {user}")
                    print(f"channel = {channel}")
                    print(f"= {project_name}/{actual_version}@{user}/{channel}")
                    print(f"recipe_id_latest = {project_name}/latest@{user}/{channel}")
                    print(f"semver_full = {actual_version}")
                    print(f"is_release_branch = {str(is_release_branch).lower()}")
                    print("::endgroup::")
                shell: python