#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import argparse, sys
from itertools import combinations

from qpid_dispatch_internal.tools.command import (main,
                                                  UsageError,
                                                  parse_args_qdstat,
                                                  parse_args_qdmanage,
                                                  _qdmanage_parser,
                                                  _qdstat_parser,
                                                  version_supports_mutually_exclusive_arguments)

from system_test import unittest

def mock_error(self, message):
    raise ValueError(message)

argparse.ArgumentParser.error = mock_error

# Since BusManager file is definded in tools/qdmanage.in -> tools/qdmanage
# otherwise it could be just imported
class FakeBusManager:
    def displayGeneral(self): pass
    def displayConnections(self): pass
    def displayRouterLinks(self): pass
    def displayRouterNodes(self): pass
    def displayEdges(self): pass
    def displayAddresses(self): pass
    def displayMemory(self): pass
    def displayPolicy(self): pass
    def displayVhosts(self): pass
    def displayVhostgroups(self): pass
    def displayVhoststats(self): pass
    def displayAutolinks(self): pass
    def displayLinkRoutes(self): pass
    def displayLog(self): pass
    def show_all(self): pass

FBM = FakeBusManager

class TestParseArgsQdstat(unittest.TestCase):
    def setUp(self):
        self.parser = _qdstat_parser(BusManager=FBM)

    def test_parse_args_qdstat_print_help(self):
        self.parser.print_help()

    def test_parse_args_qdstat_mutually_exclusive(self):
        if not version_supports_mutually_exclusive_arguments():
            #unittest.skip also not supported
            print("skipping: Mutually_exclusive options not working on python 2.6")
            return

        options1 = ["-g", "-c",
                    "-l","-n","-e","-a","-m","--autolinks","--linkroutes","--log",
                    "--all-entities"]
        options2 = ["-r", "--all-routers"]

        def _call_pairs(options):
            for options_pair in combinations(options, 2):
                with self.assertRaises(ValueError):
                    self.parser.parse_args(options_pair)

        _call_pairs(options1)
        _call_pairs(options2)

    def test_parse_args_qdstat_default(self):
        args = parse_args_qdstat(FBM, argv = [])
        self.assertEqual(FBM.displayGeneral.__name__, args.show)

    def test_parse_args_qdstat_method_show_matching(self):
        matching = [("-g", FBM.displayGeneral.__name__),
                    ("-c", FBM.displayConnections.__name__),
                    ("-l", FBM.displayRouterLinks.__name__),
                    ("-n", FBM.displayRouterNodes.__name__),
                    ("-e", FBM.displayEdges.__name__),
                    ("-a", FBM.displayAddresses.__name__),
                    ("-m", FBM.displayMemory.__name__),
                    ("--autolinks", FBM.displayAutolinks.__name__),
                    ("--linkroutes", FBM.displayLinkRoutes.__name__),
                    ("--log", FBM.displayLog.__name__),
                    ("--all-entities", FBM.show_all.__name__),
                    ]
        for option, expected in matching:
            args = self.parser.parse_args([option])
            self.assertEqual(expected, args.show)

    def test_parse_args_qdstat_limit(self):
        args = self.parser.parse_args([])
        self.assertEqual(None, args.limit)

        args = self.parser.parse_args(["--limit", "1"])
        self.assertEqual(1, args.limit)

class TestParseArgsQdmanage(unittest.TestCase):
    def setUp(self):
        self.operations = ["HERE", "SOME", "OPERATIONS"]
        self.parser = _qdmanage_parser(operations=self.operations)

    def test_parse_args_qdmanage_print_help(self):
        self.parser.print_help()

    def test_parse_args_qdmanage_operation_no_args(self):
        argv = "-r r1 QUERY --type some --name the_name -b 127.0.0.1:5672"
        opts, args = self.parser.parse_known_args(argv.split())
        self.assertEqual("QUERY", args[0])

    def test_parse_args_qdmanage_operation_and_args(self):
        argv = "-r r1 QUERY arg1=val1 --type some other=argument --name the_name -b 127.0.0.1:5672"
        opts, args = self.parser.parse_known_args(argv.split())
        self.assertEqual(["QUERY", "arg1=val1", "other=argument"], args)


class TestMain(unittest.TestCase):
    def test_main(self):
        def run_success(argv):
            self.assertEqual(sys.argv, argv)

        def run_raises(argv, _Exception):
            run_success(argv)
            raise _Exception("some")

        def run_raises_UsageError(argv):
            run_raises(argv, UsageError)

        def run_raises_Exception(argv):
            run_raises(argv, Exception)

        def run_raises_KeyboardInterrupt(argv):
            run_raises(argv, KeyboardInterrupt)

        self.assertEqual(0, main(run_success))
        failed_runs = [
            #run_raises_UsageError, ##uncomment this exposes bug
            run_raises_Exception,
            run_raises_KeyboardInterrupt,
        ]
        for run in failed_runs:
            self.assertEqual(1, main(run))

if __name__ == '__main__':
    unittest.main()

