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