#    Copyright 2017 Mirantis, Inc.
#
#    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.
from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
from tcp_tests.utils import run_jenkins_job
from tcp_tests.utils import get_jenkins_job_stages
from tcp_tests import logger
from tcp_tests.managers.jenkins import client

LOG = logger.logger


class DrivetrainManager(ExecuteCommandsMixin):
    """docstring for DrivetrainManager"""

    __config = None
    __underlay = None

    def __init__(self, config, underlay, salt=None):
        self.__config = config
        self.__underlay = underlay
        self._salt = salt
        super(DrivetrainManager, self).__init__(
            config=config, underlay=underlay)

    def install(self, commands):
        self.execute_commands(commands,
                              label='Install Drivetrain Tools')
        self.__config.drivetrain.drivetrain_installed = True

    def start_job_on_jenkins(
            self,
            job_name,
            jenkins_tgt='I@docker:client:stack:jenkins and cid01*',
            **kwargs):
        """
        Starts job with specific parameters on cluster Jenkins

        Method accept any param:
            job_parameters=None,
            job_output_prefix='',
            jenkins_tgt='I@salt:master' or
              'I@docker:client:stack:jenkins and cid01*'
            start_timeout=1800,
            build_timeout=3600 * 4,
            verbose=False

        :param job_name: string
        :param jenkins_tgt: string,  node to run jenkins in salt-style
        :return: string, Result of passed job, "SUCCESS"| "FAILED" | "UNSTABLE"
        """
        jenkins_url, jenkins_user, jenkins_pass = self.get_jenkins_creds(
            tgt=jenkins_tgt)

        jenkins = client.JenkinsClient(host=jenkins_url,
                                       username=jenkins_user,
                                       password=jenkins_pass)
        build_number = jenkins.job_info(job_name)['nextBuildNumber']

        job_result = run_jenkins_job.run_job(
            host=jenkins_url,
            username=jenkins_user,
            password=jenkins_pass,
            job_name=job_name,
            **kwargs)

        (description, stages) = get_jenkins_job_stages.get_deployment_result(
            host=jenkins_url,
            username=jenkins_user,
            password=jenkins_pass,
            job_name=job_name,
            build_number='lastBuild')

        LOG.info(description)
        LOG.info('\n'.join(stages))

        job_description = "{description}. \n\n{stages}"\
            .format(description=description,
                    stages='\n'.join(stages))

        job_log = jenkins.get_build_output(job_name, build_number)

        with open('tmp/' + job_name + str(build_number) + '.log', 'wb') as f:
            f.write(job_log.encode('utf-8'))

        if job_result != 'SUCCESS':
            LOG.warning("{0}\n{1}".format(description, '\n'.join(stages)))
        return job_result, job_description

    def get_jenkins_creds(self, tgt):
        """
        Requests Jenkins's login parameters from pillars from desired node

        :return: tuple {jenkins_url, jenkins_user, jenkins_pass}
        """
        jenkins_host = self._salt.get_single_pillar(
            tgt=tgt, pillar="jenkins:client:master:host")
        if jenkins_host is None:
            raise Exception(
                "Can't find 'jenkins:client:master' pillar on {tgt} node."
                .format(tgt=tgt))
        jenkins_port = self._salt.get_single_pillar(
            tgt=tgt, pillar="jenkins:client:master:port")
        jenkins_protocol = self._salt.get_single_pillar(
            tgt=tgt, pillar="jenkins:client:master:proto")
        jenkins_url = '{0}://{1}:{2}'.format(jenkins_protocol,
                                             jenkins_host,
                                             jenkins_port)
        jenkins_user = self._salt.get_single_pillar(
            tgt=tgt, pillar="jenkins:client:master:username")
        jenkins_pass = self._salt.get_single_pillar(
            tgt=tgt, pillar="jenkins:client:master:password")
        return jenkins_url, jenkins_user, jenkins_pass

    def check_job_exists_on_jenkins(
            self,
            job_name,
            jenkins_tgt='I@docker:client:stack:jenkins and cid01*'
            ):
        jenkins_url, jenkins_user, jenkins_pass = self.get_jenkins_creds(
            tgt=jenkins_tgt)

        jenkins = client.JenkinsClient(host=jenkins_url,
                                       username=jenkins_user,
                                       password=jenkins_pass)
        result = jenkins.find_jobs(job_name)
        return result
