#!/usr/bin/python3

# Copyright (c) 2009-2011, Benjamin Drung <bdrung@debian.org>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import getopt
import os
import sys

from moz_version import (compare_versions, convert_debian_to_moz_version,
                         convert_moz_to_debian_version)

# error codes
COMMAND_LINE_SYNTAX_ERROR = 2
INVALID_COMPARATOR = 3
EMPTY_VERSION_STRING = 4

COMPARATORS = ("lt", "le", "eq", "ne", "ge", "gt")


def moz_version_compare(version1, comparator, version2, silent=False,
                        verbose=False):
    """Return true if the expression version1 comparator version2 is valid,
       otherwise false"""
    if comparator not in COMPARATORS:
        if not silent:
            print("E: The comparator " + comparator + \
                                 " is not valid. It should one of " + \
                                 ", ".join(COMPARATORS) + ".", file=sys.stderr)
        sys.exit(INVALID_COMPARATOR)

    if version1.strip() == "" or version2.strip() == "":
        if not silent:
            print("E: At least one version string is empty.", file=sys.stderr)
        sys.exit(EMPTY_VERSION_STRING)

    if verbose:
        symbol = {"lt": "<", "le": "<=", "eq": "=", "ne": "!=",
                  "ge": ">=", "gt": ">"}
        print("I: Comparing %s %s %s." % \
              (version1, symbol[comparator], version2))

    if comparator == "lt":
        return compare_versions(version1, version2, verbose) < 0
    elif comparator == "le":
        return compare_versions(version1, version2, verbose) <= 0
    elif comparator == "eq":
        return compare_versions(version1, version2, verbose) == 0
    elif comparator == "ne":
        return compare_versions(version1, version2, verbose) != 0
    elif comparator == "ge":
        return compare_versions(version1, version2, verbose) >= 0
    elif comparator == "gt":
        return compare_versions(version1, version2, verbose) > 0
    raise NotImplementedError("Comparator '%s' not implemented." % (comparator))


def usage(output):
    name = os.path.basename(sys.argv[0])
    print("""Usage: %s [options] action

Actions:
  -c, --compare version1 comparator version2
                           compare both Mozilla version numbers
                           comparator must be one of %s
  -d, --to-deb version     converts Mozilla into a Debian upstream version
  -m, --to-moz version     converts Debian into a Mozilla version

Options:
  -h, --help               display this help and exit
  -s, --silent             do not print anything and die silent on errors
  -v, --verbose            print more information

See %s(1) for more info.""" % (name, ", ".join(COMPARATORS), name))


def main():
    try:
        long_opts = ["compare", "help", "silent", "to-deb", "to-moz", "verbose"]
        opts, args = getopt.gnu_getopt(sys.argv[1:], "cdhmsv", long_opts)
    except getopt.GetoptError as e:
        # print help information and exit:
        print(e, file=sys.stderr)
        usage(sys.stderr)
        sys.exit(COMMAND_LINE_SYNTAX_ERROR)

    actions = set()
    silent = False
    verbose = False

    for o, _ in opts:
        if o in ("-c", "--compare"):
            actions.add("compare")
        elif o in ("-d", "--to-deb"):
            actions.add("to-deb")
        elif o in ("-h", "--help"):
            usage(sys.stdout)
            sys.exit()
        elif o in ("-m", "--to-moz"):
            actions.add("to-moz")
        elif o in ("-s", "--silent"):
            silent = True
        elif o in ("-v", "--verbose"):
            verbose = True
        else:
            assert False, "unhandled option"

    if len(actions) != 1:
        if not silent:
            print("E: You must specify an action.", file=sys.stderr)
            usage(sys.stderr)
        sys.exit(COMMAND_LINE_SYNTAX_ERROR)

    action = actions.pop()

    if action == "compare":
        if len(args) != 3:
            if not silent:
                usage(sys.stderr)
            sys.exit(COMMAND_LINE_SYNTAX_ERROR)
        if moz_version_compare(args[0], args[1], args[2], silent, verbose):
            if verbose:
                print("I: Compare expression true.")
            sys.exit(0)
        else:
            if verbose:
                print("I: Compare expression false.")
            sys.exit(1)
    elif action == "to-deb":
        if len(args) != 1:
            if not silent:
                print("E: The action --to-deb takes exactly " + \
                                     "one argument.", file=sys.stderr)
            sys.exit(COMMAND_LINE_SYNTAX_ERROR)
        print(convert_moz_to_debian_version(args[0], 0, verbose))
    elif action == "to-moz":
        if len(args) != 1:
            if not silent:
                print("E: The action --to-moz takes exactly " + \
                                     "one argument.", file=sys.stderr)
            sys.exit(COMMAND_LINE_SYNTAX_ERROR)
        print(convert_debian_to_moz_version(args[0]))

if __name__ == "__main__":
    main()
