on:
  push:
    paths:
      - "**"
  pull_request:
    paths:
      - "**"
  workflow_dispatch:

jobs:
  build_data:
    name: Build data
    strategy:
      matrix:
        package: [basemap_data, basemap_data_hires]
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Build data sdist and wheel
        run: |
          cd data/${{ matrix.package }}
          python -m pip install build wheel
          python -m build

      - name: Upload data sdist and wheel
        uses: actions/upload-artifact@v4
        with:
          path: |
            data/${{ matrix.package }}/dist/*.tar.gz
            data/${{ matrix.package }}/dist/*.whl
          name: dist-${{ matrix.package }}

  build_sdist:
    name: Build sdist
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Build basemap sdist
        run: |
          python -m pip install build
          python -m build --sdist

      - name: Upload basemap sdist
        uses: actions/upload-artifact@v4
        with:
          path: dist/*.tar.gz
          name: dist-basemap-sdist

  build_wheels:
    name: Build wheels
    needs: [build_sdist]
    strategy:
      matrix:
        os: [ubuntu-22.04, windows-2022, macos-13, macos-14]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Download basemap sdist
        uses: actions/download-artifact@v4
        with:
          name: dist-basemap-sdist
          path: ./sdist/

      - name: Extract basemap sdist (Linux/macOS)
        if: runner.os != 'Windows'
        shell: bash
        run: |
          # Create extraction directory in the workspace
          mkdir -p ./sdist_extract

          # Extract with tar using wildcard
          tar -xvf ./sdist/*.tar.gz -C ./sdist_extract

          # Get the extracted directory name
          EXTRACTED_DIR="$(ls -d ./sdist_extract/*/ | head -1)"

          # Verify contents
          ls -la "${EXTRACTED_DIR}"

          # Set the environment variable
          echo "SDIST_DIR=$(pwd)/${EXTRACTED_DIR}" >> $GITHUB_ENV

      - name: Extract basemap sdist (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          # Create extraction directory in the workspace
          New-Item -ItemType Directory -Force -Path "sdist_extract"

          # Extract with tar using the specific file path (no wildcard)
          $tarball = Get-ChildItem -Path "sdist" -Filter "*.tar.gz" | Select-Object -First 1
          tar -xvf $tarball.FullName -C "sdist_extract"

          # Get the extracted directory name
          $extractedDir = (Get-ChildItem -Path "sdist_extract" -Directory | Select-Object -First 1).FullName

          # Verify contents
          Get-ChildItem "$extractedDir"

          # Set the environment variable
          echo "SDIST_DIR=$extractedDir" | Out-File -FilePath $env:GITHUB_ENV -Append

      - name: Build basemap wheels from sdist
        uses: pypa/cibuildwheel@v2.22.0
        env:
          CIBW_ARCHS: "native"
          CIBW_BUILD: "cp39* cp310* cp311* cp312* cp313*"
          CIBW_BUILD_VERBOSITY: 1
          CIBW_SKIP: "*-musllinux_*"
          CIBW_BEFORE_ALL: "python {project}/.github/workflows/run_before_all.py"
          CIBW_BEFORE_TEST: "python -m pip install {project}/data/basemap_data {project}/data/basemap_data_hires"
          CIBW_TEST_EXTRAS: "test"
          CIBW_TEST_COMMAND: "python -m pytest {project}/test"
          CIBW_ENVIRONMENT: >-
            GEOS_VERSION="3.6.5"
            GEOS_DIR="$(pwd)/extern"
            GEOS_NJOBS=4
            PIP_PREFER_BINARY=1
            PYTHONUNBUFFERED=1
            LD_LIBRARY_PATH="${GEOS_DIR}/lib"
          # LD_LIBRARY_PATH in environment is needed by
          # auditwheel (Linux) and delocate (MacOS).
        with:
          package-dir: ${{ env.SDIST_DIR }}
          output-dir: "dist"
          # Set `package-dir` to a folder with the extracted sdist;
          # otherwise, `cibuildwheel` uses `python -m pip wheel` or
          # `python -m build --wheel` with the repository package
          # folder and we cannot guarantee that wheels can be built
          # from the sdist.

      - name: Upload basemap wheels
        uses: actions/upload-artifact@v4
        with:
          path: dist/*.whl
          name: dist-basemap-wheels-${{ matrix.os }}

  check:
    name: Check packages
    needs: [build_data, build_sdist, build_wheels]
    runs-on: ubuntu-22.04
    steps:
      - name: Download basemap and data packages
        uses: actions/download-artifact@v4
        with:
          path: dist
          pattern: "dist-*"
          merge-multiple: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Check packages with twine
        run: |
          python -m pip install twine
          python -m twine check dist/*.tar.gz
          python -m twine check dist/*.whl

  docs:
    name: Build docs
    needs: [check]
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Download data packages
        uses: actions/download-artifact@v4
        with:
          path: ./data_packages/
          pattern: "dist-basemap_data*"
          merge-multiple: true

      - name: Download basemap wheels for Linux
        uses: actions/download-artifact@v4
        with:
          path: ./wheels/
          pattern: "dist-basemap-wheels-ubuntu-*"
          merge-multiple: true

      - name: Install basemap and data packages
        run: |
          # Get Python version.
          IMPL=cp$(python -c "import sys; print('{0}{1}'.format(*sys.version_info[:2]))")

          # Install data packages.
          python -m pip install ./data_packages/*.whl

          # Install basemap wheel matching current Python version.
          WHEEL=$(find ./wheels -name "*-${IMPL}-${IMPL}*.whl" | head -1)
          if [ -n "${WHEEL}" ]; then
            python -m pip install "${WHEEL}"
          else
            echo "No matching wheel found for ${IMPL}-${IMPL}"
            exit 1
          fi

      - name: Install docs requirements
        run: |
          python -m pip install -r dep/requirements-doc.txt

      - name: Run sphinx
        run: |
          python -m sphinx -j auto doc/source public

      - name: Upload docs artifacts
        uses: actions/upload-artifact@v4
        with:
          name: docs
          path: public

      - name: Upload github-pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          name: github-pages
          path: public

  pages:
    name: Deploy docs
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    needs: [docs]
    runs-on: ubuntu-22.04
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    permissions:
      pages: write
      id-token: write
    steps:
      - name: Deploy github-pages
        uses: actions/deploy-pages@v3
        id: deployment

  upload:
    name: Upload packages
    needs: [check]
    runs-on: ubuntu-22.04
    environment: PyPI
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    steps:
      - name: Download basemap and data packages
        uses: actions/download-artifact@v4
        with:
          path: dist
          pattern: "dist-*"
          merge-multiple: true

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_TOKEN }}
          repository-url: ${{ secrets.PYPI_REPOSITORY_URL }}
          skip-existing: true
