# Copyright (c) 2013 The Chromium OS Authors.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#

import multiprocessing
import os
import sys

import board
import bsettings
from builder import Builder
import gitutil
import patchstream
import terminal
import toolchain

def GetPlural(count):
    """Returns a plural 's' if count is not 1"""
    return 's' if count != 1 else ''

def GetActionSummary(is_summary, count, selected, options):
    """Return a string summarising the intended action.

    Returns:
        Summary string.
    """
    count = (count + options.step - 1) / options.step
    str = '%s %d commit%s for %d boards' % (
        'Summary of' if is_summary else 'Building', count, GetPlural(count),
        len(selected))
    str += ' (%d thread%s, %d job%s per thread)' % (options.threads,
            GetPlural(options.threads), options.jobs, GetPlural(options.jobs))
    return str

def ShowActions(series, why_selected, boards_selected, builder, options):
    """Display a list of actions that we would take, if not a dry run.

    Args:
        series: Series object
        why_selected: Dictionary where each key is a buildman argument
                provided by the user, and the value is the boards brought
                in by that argument. For example, 'arm' might bring in
                400 boards, so in this case the key would be 'arm' and
                the value would be a list of board names.
        boards_selected: Dict of selected boards, key is target name,
                value is Board object
        builder: The builder that will be used to build the commits
        options: Command line options object
    """
    col = terminal.Color()
    print 'Dry run, so not doing much. But I would do this:'
    print
    print GetActionSummary(False, len(series.commits), boards_selected,
            options)
    print 'Build directory: %s' % builder.base_dir
    for upto in range(0, len(series.commits), options.step):
        commit = series.commits[upto]
        print '   ', col.Color(col.YELLOW, commit.hash, bright=False),
        print commit.subject
    print
    for arg in why_selected:
        if arg != 'all':
            print arg, ': %d boards' % why_selected[arg]
    print ('Total boards to build for each commit: %d\n' %
            why_selected['all'])

def DoBuildman(options, args):
    """The main control code for buildman

    Args:
        options: Command line options object
        args: Command line arguments (list of strings)
    """
    gitutil.Setup()

    bsettings.Setup()
    options.git_dir = os.path.join(options.git, '.git')

    toolchains = toolchain.Toolchains()
    toolchains.Scan(options.list_tool_chains)
    if options.list_tool_chains:
        toolchains.List()
        print
        return

    # Work out how many commits to build. We want to build everything on the
    # branch. We also build the upstream commit as a control so we can see
    # problems introduced by the first commit on the branch.
    col = terminal.Color()
    count = options.count
    if count == -1:
        if not options.branch:
            str = 'Please use -b to specify a branch to build'
            print col.Color(col.RED, str)
            sys.exit(1)
        count = gitutil.CountCommitsInBranch(options.git_dir, options.branch)
        count += 1   # Build upstream commit also

    if not count:
        str = ("No commits found to process in branch '%s': "
               "set branch's upstream or use -c flag" % options.branch)
        print col.Color(col.RED, str)
        sys.exit(1)

    # Work out what subset of the boards we are building
    boards = board.Boards()
    boards.ReadBoards(os.path.join(options.git, 'boards.cfg'))
    why_selected = boards.SelectBoards(args)
    selected = boards.GetSelected()
    if not len(selected):
        print col.Color(col.RED, 'No matching boards found')
        sys.exit(1)

    # Read the metadata from the commits. First look at the upstream commit,
    # then the ones in the branch. We would like to do something like
    # upstream/master~..branch but that isn't possible if upstream/master is
    # a merge commit (it will list all the commits that form part of the
    # merge)
    range_expr = gitutil.GetRangeInBranch(options.git_dir, options.branch)
    upstream_commit = gitutil.GetUpstream(options.git_dir, options.branch)
    series = patchstream.GetMetaDataForList(upstream_commit, options.git_dir,
            1)
    series = patchstream.GetMetaDataForList(range_expr, options.git_dir, None,
            series)

    # By default we have one thread per CPU. But if there are not enough jobs
    # we can have fewer threads and use a high '-j' value for make.
    if not options.threads:
        options.threads = min(multiprocessing.cpu_count(), len(selected))
    if not options.jobs:
        options.jobs = max(1, (multiprocessing.cpu_count() +
                len(selected) - 1) / len(selected))

    if not options.step:
        options.step = len(series.commits) - 1

    # Create a new builder with the selected options
    output_dir = os.path.join('..', options.branch)
    builder = Builder(toolchains, output_dir, options.git_dir,
            options.threads, options.jobs, checkout=True,
            show_unknown=options.show_unknown, step=options.step)
    builder.force_config_on_failure = not options.quick

    # For a dry run, just show our actions as a sanity check
    if options.dry_run:
        ShowActions(series, why_selected, selected, builder, options)
    else:
        builder.force_build = options.force_build

        # Work out which boards to build
        board_selected = boards.GetSelectedDict()

        print GetActionSummary(options.summary, count, board_selected, options)

        if options.summary:
            # We can't show function sizes without board details at present
            if options.show_bloat:
                options.show_detail = True
            builder.ShowSummary(series.commits, board_selected,
                    options.show_errors, options.show_sizes,
                    options.show_detail, options.show_bloat)
        else:
            builder.BuildBoards(series.commits, board_selected,
                    options.show_errors, options.keep_outputs)
