# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 IBM Corp.
#
#    Licensed 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 json
import os
import shutil
import sys

from oslo.config import cfg

from tempest.common.rest_client import RestClient
from tempest import config

CONF = config.TempestConfig()


class CoverageClientJSON(RestClient):

    def __init__(self, config, username, password, auth_url, tenant_name=None):
        super(CoverageClientJSON, self).__init__(config, username, password,
                                                 auth_url, tenant_name)
        self.service = self.config.compute.catalog_type

    def start_coverage(self):
        post_body = {
            'start': {},
        }
        post_body = json.dumps(post_body)
        return self.post('os-coverage/action', post_body, self.headers)

    def start_coverage_combine(self):
        post_body = {
            'start': {
                'combine': True,
            },
        }
        post_body = json.dumps(post_body)
        return self.post('os-coverage/action', post_body, self.headers)

    def stop_coverage(self):
        post_body = {
            'stop': {},
        }
        post_body = json.dumps(post_body)
        resp, body = self.post('os-coverage/action', post_body, self.headers)
        body = json.loads(body)
        return resp, body

    def report_coverage_xml(self, file=None):
        post_body = {
            'report': {
                'file': 'coverage.report',
                'xml': True,
            },
        }
        if file:
            post_body['report']['file'] = file
        post_body = json.dumps(post_body)
        resp, body = self.post('os-coverage/action', post_body, self.headers)
        body = json.loads(body)
        return resp, body

    def report_coverage(self, file=None):
        post_body = {
            'report': {
                'file': 'coverage.report',
            },
        }
        if file:
            post_body['report']['file'] = file
        post_body = json.dumps(post_body)
        resp, body = self.post('os-coverage/action', post_body, self.headers)
        body = json.loads(body)
        return resp, body

    def report_coverage_html(self, file=None):
        post_body = {
            'report': {
                'file': 'coverage.report',
                'html': True,
            },
        }
        if file:
            post_body['report']['file'] = file
        post_body = json.dumps(post_body)
        resp, body = self.post('os-coverage/action', post_body, self.headers)
        body = json.loads(body)
        return resp, body


def parse_opts(argv):
    cli_opts = [
        cfg.StrOpt('command',
                   short='c',
                   default='',
                   help="This required argument is used to specify the "
                        "coverage command to run. Only 'start', "
                        "'stop', or 'report' are valid fields."),
        cfg.StrOpt('filename',
                   default='tempest-coverage',
                   help="Specify a filename to be used for generated report "
                        "files"),
        cfg.BoolOpt('xml',
                    default=False,
                    help='Generate XML reports instead of text'),
        cfg.BoolOpt('html',
                    default=False,
                    help='Generate HTML reports instead of text'),
        cfg.BoolOpt('combine',
                    default=False,
                    help='Generate a single report for all services'),
        cfg.StrOpt('output',
                   short='o',
                   default=None,
                   help='Optional directory to copy generated coverage data or'
                        ' reports into. This directory must not already exist '
                        'it will be created')
    ]
    CLI = cfg.ConfigOpts()
    CLI.register_cli_opts(cli_opts)
    CLI(argv[1:])
    return CLI


def main(argv):
    CLI = parse_opts(argv)
    client_args = (CONF, CONF.identity.admin_username,
                   CONF.identity.admin_password, CONF.identity.uri,
                   CONF.identity.admin_tenant_name)
    coverage_client = CoverageClientJSON(*client_args)

    if CLI.command == 'start':
        if CLI.combine:
            coverage_client.start_coverage_combine()
        else:
            coverage_client.start_coverage()

    elif CLI.command == 'stop':
        resp, body = coverage_client.stop_coverage()
        if not resp['status'] == '200':
            print 'coverage stop failed with: %s:' % (resp['status'] + ': '
                                                      + body)
            exit(int(resp['status']))
        path = body['path']
        if CLI.output:
            shutil.copytree(path, CLI.output)
        else:
            print "Data files located at: %s" % path

    elif CLI.command == 'report':
        if CLI.xml:
            resp, body = coverage_client.report_coverage_xml(file=CLI.filename)
        elif CLI.html:
            resp, body = coverage_client.report_coverage_html(
                file=CLI.filename)
        else:
            resp, body = coverage_client.report_coverage(file=CLI.filename)
        if not resp['status'] == '200':
            print 'coverage report failed with: %s:' % (resp['status'] + ': '
                                                        + body)
            exit(int(resp['status']))
        path = body['path']
        if CLI.output:
            if CLI.html:
                shutil.copytree(path, CLI.output)
            else:
                path = os.path.dirname(path)
                shutil.copytree(path, CLI.output)
        else:
            if not CLI.html:
                path = os.path.dirname(path)
            print 'Report files located at: %s' % path

    else:
        print 'Invalid command'
        exit(1)


if __name__ == "__main__":
    main(sys.argv)
