#!/usr/bin/env python
# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import dataclasses
import json
import os
import re
import sys
import urllib.request

_BASE_URL = 'https://mirrors.edge.kernel.org/pub/linux/utils/util-linux'


def _parse_index_page(url):
    entries = []

    with urllib.request.urlopen(url) as response:
        html = response.read().decode().splitlines()
        for line in html:
            if not line.startswith('<a href='):
                continue
            match = re.match(r'^<a href="([^"]+)">.*</a>\s+', line)
            name = match.group(1)
            entries.append(name)

    return entries


def _try_int(x):
    try:
        return int(x)
    except ValueError:
        return x


def _as_version_tuple(version: str):
    return [_try_int(x) for x in re.split(r'[-.]', version)]


def do_latest():
    """Retrieve latest version.

    This is kind of hacky, but the Apache default index page hasn't changed
    in 15+ years so it should be ok.

    This package only uses major.minor for folders but major.minor.bugfix in
    tarball names. So if the most recent folder is '2.25' and within '2.25'
    there are tarballs with versions '2.25', '2.25.1', and '2.25.2', we need
    to retrieve '2.25.2' since that's the current version.
    """
    entries = _parse_index_page(_BASE_URL)
    matches = []
    for entry in entries:
        match = re.match(r'^v(\d+(?:\.\d+)*)/?$', entry)
        if match:
            matches.append(match.group(1))

    # Need to loop over high numbers since the latest folder might only be
    # release candidates. If so, we need to go to the next folder.
    versions = sorted(matches, key=_as_version_tuple)

    matches = []
    for ver in reversed(versions):
        entries = _parse_index_page(f'{_BASE_URL}/v{ver}')
        for entry in entries:
            if not entry.startswith('util-linux-'):
                continue
            if not entry.endswith('.tar.gz'):
                continue
            if '-rc' in entry:
                continue
            matches.append(entry[len('util-linux-'):-len('.tar.gz')])
        if matches:
            break

    current = max(matches, key=_as_version_tuple)

    print(current)
    return 0


def get_download_url(version, platform):
    """Get URL of the given version and platform.

    See docstring for do_latest() for details about URLs for this package.
    Basically, we need 'BASE/vMAJ.MIN/util-linux-FULLVER.tar.gz'.
    """
    major, minor, *rest = version.rstrip('/').split('.')
    url = f'{_BASE_URL}/v{major}.{minor}/util-linux-{version}.tar.gz'
    manifest = {'url': [url], 'ext': '.tar.gz'}
    print(json.dumps(manifest))


def main():
  ap = argparse.ArgumentParser()
  sub = ap.add_subparsers()

  latest = sub.add_parser("latest")
  latest.set_defaults(func=lambda _opts: do_latest())

  download = sub.add_parser("get_url")
  download.set_defaults(
    func=lambda opts: get_download_url(
      os.environ['_3PP_VERSION'], os.environ['_3PP_PLATFORM']
    )
  )

  opts = ap.parse_args()
  return opts.func(opts)


if __name__ == '__main__':
    sys.exit(main())
