# 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)
