# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
This module contains functions to get or update stable version for a given
board.

The valid actions are:
list:   Show version of a given board or list all boards and their stable
        versions if --board option is not specified.
modify: Set the stable version of a given board to the given value.
delete: Delete the stable version of a given board. So its stable version will
        use the value for board `DEFAULT`.
"""

import common

from autotest_lib.cli import topic_common


class stable_version(topic_common.atest):
    """stable_version class

    atest stable_version [list|delete|modify] <options>
    """
    usage_action = '[list|delete|modify]'
    topic = msg_topic = 'stable_version'
    msg_items = '<stable_version>'

    def __init__(self):
        """Add to the parser the options common to all the
        stable_version actions.
        """
        super(stable_version, self).__init__()

        self.parser.add_option('-b', '--board',
                               help='Name of the board',
                               type='string',
                               default=None,
                               metavar='BOARD')

        self.topic_parse_info = topic_common.item_parse_info(
                attribute_name='board', use_leftover=True)


    def parse(self):
        """Parse command arguments.
        """
        board_info = topic_common.item_parse_info(attribute_name='board')
        (options, leftover) = super(stable_version, self).parse([board_info])

        self.board = options.board
        return (options, leftover)


    def output(self, results):
        """Display output.

        For most actions, the return is a string message, no formating needed.

        @param results: return of the execute call.
        """
        if results:
            print results


class stable_version_help(stable_version):
    """Just here to get the atest logic working. Usage is set by its parent.
    """
    pass


class stable_version_list(stable_version):
    """atest stable_version list [--board <board>]"""

    def execute(self):
        """Execute list stable version action.
        """
        if self.board:
            version = self.execute_rpc(op='get_stable_version',
                                       board=self.board)
            return {self.board: version}
        else:
            return self.execute_rpc(op='get_all_stable_versions')


    def output(self, results):
        """Display output.

        @param results: A dictionary of board:version.
        """
        format = '%-12s| %-20s'
        print '='*30
        print format % ('board', 'version')
        print '-'*30
        for board,version in results.iteritems():
            print format % (board, version)
        print '='*30


class stable_version_modify(stable_version):
    """atest stable_version modify --board <board> --version <version>

    Change the stable version of a given board to the given value.
    """

    def __init__(self):
        """Add to the parser the options common to all the
        stable_version actions.
        """
        super(stable_version_modify, self).__init__()

        self.parser.add_option('-i', '--version',
                               help='Stable version.',
                               type='string',
                               metavar='VERSION')

        self.topic_parse_info = topic_common.item_parse_info(
                attribute_name='board', use_leftover=True)


    def parse(self):
        """Parse command arguments.
        """
        options,leftover = super(stable_version_modify, self).parse()

        self.version = options.version
        if not self.board or not self.version:
            self.invalid_syntax('Both --board and --version arguments must be '
                                'specified.')


    def execute(self):
        """Execute delete stable version action.
        """
        current_version = self.execute_rpc(op='get_stable_version',
                                           board=self.board)
        if current_version == self.version:
            print ('Board %s already has stable version of %s.' %
                   (self.board, self.version))
            return

        self.execute_rpc(op='set_stable_version', board=self.board,
                         version=self.version)
        print ('Stable version for board %s is changed from %s to %s.' %
               (self.board, current_version, self.version))


class stable_version_delete(stable_version):
    """atest stable_version delete --board <board>

    Delete a stable version entry in afe_stable_versions table for a given
    board, so default stable version will be used.
    """

    def parse(self):
        """Parse command arguments.
        """
        super(stable_version_delete, self).parse()
        if not self.board:
            self.invalid_syntax('`board` argument must be specified to delete '
                                'a stable version entry.')
        if self.board == 'DEFAULT':
            self.invalid_syntax('Stable version for board DEFAULT can not be '
                                'deleted.')


    @topic_common.atest.require_confirmation(
            'Are you sure to delete stable version for the given board?')
    def execute(self):
        """Execute delete stable version action.
        """
        self.execute_rpc(op='delete_stable_version', board=self.board)
        print 'Stable version for board %s is deleted.' % self.board
        default_stable_version = self.execute_rpc(op='get_stable_version')
        print ('Stable version for board %s is default to %s' %
               (self.board, default_stable_version))
