# Copyright (c) 2010 Google Inc. All rights reserved.
# Copyright (c) 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""blink_tool.py is a tool with multiple sub-commands with different purposes.

It has commands for printing expectations, fetching new test baselines, etc.
These commands don't necessarily have anything to do with each other.
"""

import logging
import optparse
import sys

from blinkpy.common.host import Host
from blinkpy.tool.commands.analyze_baselines import AnalyzeBaselines
from blinkpy.tool.commands.command import HelpPrintingOptionParser
from blinkpy.tool.commands.copy_existing_baselines import CopyExistingBaselines
from blinkpy.tool.commands.flaky_tests import FlakyTests
from blinkpy.tool.commands.help_command import HelpCommand
from blinkpy.tool.commands.optimize_baselines import OptimizeBaselines
from blinkpy.tool.commands.pretty_diff import PrettyDiff
from blinkpy.tool.commands.queries import CrashLog
from blinkpy.tool.commands.queries import PrintBaselines
from blinkpy.tool.commands.queries import PrintExpectations
from blinkpy.tool.commands.rebaseline import Rebaseline
from blinkpy.tool.commands.rebaseline_cl import RebaselineCL
from blinkpy.tool.commands.rebaseline_test import RebaselineTest

_log = logging.getLogger(__name__)


class BlinkTool(Host):
    # FIXME: It might make more sense if this class had a Host attribute
    # instead of being a Host subclass.

    global_options = [
        optparse.make_option(
            '-v',
            '--verbose',
            action='store_true',
            dest='verbose',
            default=False,
            help='enable all logging'),
        optparse.make_option(
            '-d',
            '--directory',
            action='append',
            default=[],
            help='Directory to look at for changed files'),
    ]

    def __init__(self, path):
        super(BlinkTool, self).__init__()
        self._path = path
        self.commands = [
            AnalyzeBaselines(),
            CopyExistingBaselines(),
            CrashLog(),
            FlakyTests(),
            OptimizeBaselines(),
            PrettyDiff(),
            PrintBaselines(),
            PrintExpectations(),
            Rebaseline(),
            RebaselineCL(),
            RebaselineTest(),
        ]
        self.help_command = HelpCommand(tool=self)
        self.commands.append(self.help_command)

    def main(self, argv=None):
        argv = argv or sys.argv
        (command_name, args) = self._split_command_name_from_args(argv[1:])

        option_parser = self._create_option_parser()
        self._add_global_options(option_parser)

        command = self.command_by_name(command_name) or self.help_command
        if not command:
            option_parser.error('%s is not a recognized command', command_name)

        command.set_option_parser(option_parser)
        (options, args) = command.parse_args(args)

        result = command.check_arguments_and_execute(options, args, self)
        return result

    def path(self):
        return self._path

    @staticmethod
    def _split_command_name_from_args(args):
        # Assume the first argument which doesn't start with "-" is the command name.
        command_index = 0
        for arg in args:
            if arg[0] != '-':
                break
            command_index += 1
        else:
            return (None, args[:])

        command = args[command_index]
        return (command, args[:command_index] + args[command_index + 1:])

    def _create_option_parser(self):
        usage = 'Usage: %prog [options] COMMAND [ARGS]'
        name = optparse.OptionParser().get_prog_name()
        return HelpPrintingOptionParser(
            epilog_method=self.help_command.help_epilog,
            prog=name,
            usage=usage)

    def _add_global_options(self, option_parser):
        global_options = self.global_options or []
        for option in global_options:
            option_parser.add_option(option)

    def name(self):
        return optparse.OptionParser().get_prog_name()

    def should_show_in_main_help(self, command):
        return command.show_in_main_help

    def command_by_name(self, command_name):
        for command in self.commands:
            if command_name == command.name:
                return command
        return None
