#
# Copyright (C) 2015 The Android Open Source Project
#
# 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 __future__ import absolute_import

import json
import logging
import os.path
import re
import requests

import jenkinsapi

import gerrit

import config


def is_untrusted_committer(change_id, patch_set):
    # TODO(danalbert): Needs to be based on the account that made the comment.
    commit = gerrit.get_commit(change_id, patch_set)
    committer = commit['committer']['email']
    return not committer.endswith('@google.com')


def contains_cleanspec(change_id, patch_set):
    files = gerrit.get_files_for_revision(change_id, patch_set)
    return 'CleanSpec.mk' in [os.path.basename(f) for f in files]


def contains_bionicbb(change_id, patch_set):
    files = gerrit.get_files_for_revision(change_id, patch_set)
    return any('tools/bionicbb' in f for f in files)


def should_skip_build(info):
    if info['MessageType'] not in ('newchange', 'newpatchset', 'comment'):
        raise ValueError('should_skip_build() is only valid for new '
                         'changes, patch sets, and commits.')

    change_id = info['Change-Id']
    patch_set = info['PatchSet']

    checks = [
        is_untrusted_committer,
        contains_cleanspec,
        contains_bionicbb,
    ]
    for check in checks:
        if check(change_id, patch_set):
            return True
    return False


def clean_project(dry_run):
    username = config.jenkins_credentials['username']
    password = config.jenkins_credentials['password']
    jenkins_url = config.jenkins_url
    jenkins = jenkinsapi.api.Jenkins(jenkins_url, username, password)

    build = 'clean-bionic-presubmit'
    if build in jenkins:
        if not dry_run:
            job = jenkins[build].invoke()
            url = job.get_build().baseurl
        else:
            url = 'DRY_RUN_URL'
        logging.info('Cleaning: %s %s', build, url)
    else:
        logging.error('Failed to clean: could not find project %s', build)
    return True


def build_project(gerrit_info, dry_run, lunch_target=None):
    project_to_jenkins_map = {
        'platform/bionic': 'bionic-presubmit',
        'platform/build': 'bionic-presubmit',
        'platform/external/jemalloc': 'bionic-presubmit',
        'platform/external/libcxx': 'bionic-presubmit',
        'platform/external/libcxxabi': 'bionic-presubmit',
        'platform/external/compiler-rt': 'bionic-presubmit',
    }

    username = config.jenkins_credentials['username']
    password = config.jenkins_credentials['password']
    jenkins_url = config.jenkins_url
    jenkins = jenkinsapi.api.Jenkins(jenkins_url, username, password)

    project = gerrit_info['Project']
    change_id = gerrit_info['Change-Id']
    if project in project_to_jenkins_map:
        build = project_to_jenkins_map[project]
    else:
        build = 'bionic-presubmit'

    if build in jenkins:
        project_path = '/'.join(project.split('/')[1:])
        if not project_path:
            raise RuntimeError('bogus project: {}'.format(project))
        if project_path.startswith('platform/'):
            raise RuntimeError('Bad project mapping: {} => {}'.format(
                project, project_path))
        ref = gerrit.ref_for_change(change_id)
        params = {
            'REF': ref,
            'CHANGE_ID': change_id,
            'PROJECT': project_path
        }
        if lunch_target is not None:
            params['LUNCH_TARGET'] = lunch_target
        if not dry_run:
            _ = jenkins[build].invoke(build_params=params)
            # https://issues.jenkins-ci.org/browse/JENKINS-27256
            # url = job.get_build().baseurl
            url = 'URL UNAVAILABLE'
        else:
            url = 'DRY_RUN_URL'
        logging.info('Building: %s => %s %s %s', project, build, url,
                     change_id)
    else:
        logging.error('Unknown build: %s => %s %s', project, build, change_id)
    return True


def handle_change(gerrit_info, _, dry_run):
    if should_skip_build(gerrit_info):
        return True
    return build_project(gerrit_info, dry_run)


def drop_rejection(gerrit_info, dry_run):
    request_data = {
        'changeid': gerrit_info['Change-Id'],
        'patchset': gerrit_info['PatchSet']
    }
    url = '{}/{}'.format(config.build_listener_url, 'drop-rejection')
    headers = {'Content-Type': 'application/json;charset=UTF-8'}
    if not dry_run:
        try:
            requests.post(url, headers=headers, data=json.dumps(request_data))
        except requests.exceptions.ConnectionError as ex:
            logging.error('Failed to drop rejection: %s', ex)
            return False
    logging.info('Dropped rejection: %s', gerrit_info['Change-Id'])
    return True


def handle_comment(gerrit_info, body, dry_run):
    if 'Verified+1' in body:
        drop_rejection(gerrit_info, dry_run)

    if should_skip_build(gerrit_info):
        return True

    command_map = {
        'clean': lambda: clean_project(dry_run),
        'retry': lambda: build_project(gerrit_info, dry_run),

        'arm': lambda: build_project(gerrit_info, dry_run,
                                     lunch_target='aosp_arm-eng'),
        'aarch64': lambda: build_project(gerrit_info, dry_run,
                                         lunch_target='aosp_arm64-eng'),
        'mips': lambda: build_project(gerrit_info, dry_run,
                                      lunch_target='aosp_mips-eng'),
        'mips64': lambda: build_project(gerrit_info, dry_run,
                                        lunch_target='aosp_mips64-eng'),
        'x86': lambda: build_project(gerrit_info, dry_run,
                                     lunch_target='aosp_x86-eng'),
        'x86_64': lambda: build_project(gerrit_info, dry_run,
                                        lunch_target='aosp_x86_64-eng'),
    }

    def handle_unknown_command():
        pass    # TODO(danalbert): should complain to the commenter.

    commands = [match.group(1).strip() for match in
                re.finditer(r'^bionicbb:\s*(.+)$', body, flags=re.MULTILINE)]

    for command in commands:
        if command in command_map:
            command_map[command]()
        else:
            handle_unknown_command()

    return True


def skip_handler(gerrit_info, _, __):
    logging.info('Skipping %s: %s', gerrit_info['MessageType'],
                 gerrit_info['Change-Id'])
    return True
