#!/usr/bin/env python
# script to list the Sage packages
#  called with one argument which meight be either "installed" or "standard" or
#  "optional" or "experimental".

from __future__ import print_function

import os
import sys
import argparse
import re


if "SAGE_ROOT" not in os.environ:
    raise RuntimeError("The environment variable SAGE_ROOT must be set.")
SAGE_ROOT = os.environ["SAGE_ROOT"]


# Input parsing #
#################

parser = argparse.ArgumentParser(description="List Sage's packages")
parser.add_argument('category', choices=['standard', 'optional',
                                         'experimental', 'installed'],
                    metavar="category",
                    help="The type of packages. Can be 'standard', "
                    "'optional', 'experimental', or 'installed'.")
parser.add_argument('--dump', dest='dump', default=False, action='store_true',
                    help='Output computer-friendly format')
parser.add_argument('--no-version', dest='version', default=True,
                    action='store_false',
                    help='Do not display version numbers')
parser.add_argument('--local', dest='remote', default=True,
                    action='store_false',
                    help='Only read local data')

args = vars(parser.parse_args())

# Get the data #
################

def pkgname_split(name):
    r"""
    Split a pkgname to 'name,version'
    """
    return (name.split('-',1) + [''])[:2]

# Installed packages
SAGE_SPKG_INST=os.path.join(os.environ["SAGE_ROOT"], 'local', 'var',
                            'lib', 'sage', 'installed')
installed = dict(pkgname_split(pkgname)
                 for pkgname in os.listdir(SAGE_SPKG_INST))

# new-style packages
SAGE_PKGS = os.path.join(SAGE_ROOT, "build", "pkgs")
local = {}
for p in os.listdir(SAGE_PKGS):
    if not os.path.isfile(os.path.join(SAGE_PKGS, p, "checksums.ini")):
        continue
    with open(os.path.join(SAGE_PKGS, p, "package-version.txt")) as f:
        version = f.read().strip()
    with open(os.path.join(SAGE_PKGS, p, "type")) as f:
        if f.read().strip() == args['category']:
            local[p] = version

# remote packages
remote = {}
if args['remote'] and args['category']!='installed':
    # Get mirror URL
    MIRROR_URL = os.popen("sage-download-file --print-fastest-mirror").read().strip()

    # Load the list of packages
    try:
        # Python 3.3+
        from urllib.request import urlopen
    except ImportError:
        # Python 2.7
        from urllib2 import urlopen
    f = urlopen(MIRROR_URL+"/spkg/"+args['category']+"/list")
    packages_list_remote = f.read()
    f.close()

    if '<' in packages_list_remote:
        print(packages_list_remote)
        raise RuntimeError("There was an error while downloading the list of packages")

    remote = dict(pkgname_split(p) for p in packages_list_remote.split('\n'))

# OUTPUT #
##########

# installed
if args['category'] == 'installed':
    if args['version']:
        if args['dump']:
            for p in sorted(installed):
                print(p+" "+installed[p])
        else:
            print("{:.<40} {}\n".format("[package] ", "[version]"))
            for p in sorted(installed):
                print("{:.<40} {}".format(p, installed[p]))
    else:
        for p in sorted(installed):
            print(p)

# Any other categories
else:
    if args['version']:
        # Display the columns' name
        if not args['dump']:
            print("{:.<40} {} ({})\n".format("[package] ", "[latest version]",
                                             "[installed version]"))
        for p in sorted(set(local).union(remote)):
            line = [p, local.get(p, remote.get(p, 'not_found')),
                    installed.get(p, 'not_installed')]
            if args['dump']:
                print(' '.join(line))
            else:
                print("{:.<40} {} ({})".format(*line))
    else:
        for p in sorted(set(local).union(remote)):
            print(p)
