#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

# Utility for updating fix version for Jiras.
#
#   usage: ./gobblin-jira-version    (see config env vars below)
#

from __future__ import print_function
import json
import os
import re
import subprocess
import sys
import textwrap

# Python 3 compatibility
try:
    import urllib2 as urllib
except ImportError:
    import urllib.request as urllib
if sys.version_info[0] == 3:
    raw_input = input

try:
    import click
except ImportError:
    print("Could not find the click library. Run 'sudo pip install click' to install.")
    sys.exit(-1)

try:
    import keyring
except ImportError:
    print("Could not find the keyring library. Run 'sudo pip install keyring' to install.")
    sys.exit(-1)

try:
    import jira.client
except ImportError:
    print("Could not find jira-python library; exiting. Run 'sudo pip install jira' to install.")
    sys.exit(-1)
    
JIRA_BASE = "https://issues.apache.org/jira/browse"
JIRA_API_BASE = "https://issues.apache.org/jira"

TMP_CREDENTIALS = {}

def register(username, password):
    """ Use this function to register a JIRA account in your OS' keyring """
    keyring.set_password('gobblin-pr', username, password)
    
def validate_jira_id(jira_id):
    if not jira_id:
        return
    elif isinstance(jira_id, int):
        return 'GOBBLIN-{}'.format(abs(jira_id))

    # first look for GOBBLIN-X
    ids = re.findall("GOBBLIN-[0-9]{1,6}", jira_id)
    if len(ids) > 1:
        raise click.UsageError('Found multiple issue ids: {}'.format(ids))
    elif len(ids) == 1:
        jira_id = ids[0]
    elif not ids:
        # if we don't find GOBBLIN-X, see if jira_id is an int
        try:
            jira_id = 'GOBBLIN-{}'.format(abs(int(jira_id)))
        except ValueError:
            raise click.UsageError(
                'JIRA id must be an integer or have the form GOBBLIN-X')

    return jira_id

def update_jira_issue(fix_version):
    """
    Update JIRA issue

    fix_version: the version to assign to the Gobblin JIRAs.
    """

    # ASF JIRA username
    JIRA_USERNAME = os.environ.get("JIRA_USERNAME", '')
    if not JIRA_USERNAME:
        JIRA_USERNAME = TMP_CREDENTIALS.get('JIRA_USERNAME', '')
    # ASF JIRA password
    JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD", '')
    if not JIRA_PASSWORD:
        JIRA_PASSWORD = TMP_CREDENTIALS.get('JIRA_PASSWORD', '')

    if not JIRA_USERNAME:
        JIRA_USERNAME = click.prompt(
            click.style('Username for Gobblin JIRA', fg='blue', bold=True),
            type=str)
        click.echo(
            'Set a JIRA_USERNAME env var to avoid this prompt in the future.')
        TMP_CREDENTIALS['JIRA_USERNAME'] = JIRA_USERNAME
    if JIRA_USERNAME and not JIRA_PASSWORD:
        JIRA_PASSWORD = keyring.get_password("gobblin-pr", JIRA_USERNAME)
        if JIRA_PASSWORD:
            click.echo("Obtained password from keyring. To reset remove it there.")
    if not JIRA_PASSWORD:
        JIRA_PASSWORD = click.prompt(
            click.style('Password for Gobblin JIRA', fg='blue', bold=True),
            type=str,
            hide_input=True)
        if JIRA_USERNAME and JIRA_PASSWORD:
            if click.confirm(click.style("Would you like to store your password "
                                         "in your keyring?", fg='blue', bold=True)):
                register(JIRA_USERNAME, JIRA_PASSWORD)
        TMP_CREDENTIALS['JIRA_PASSWORD'] = JIRA_PASSWORD

    try:
        asf_jira = jira.client.JIRA(
            {'server': JIRA_API_BASE},
            basic_auth=(JIRA_USERNAME, JIRA_PASSWORD))
    except:
        raise ValueError('Could not log in to JIRA!')
          
    for jira_obj in asf_jira.search_issues('filter=12342798', startAt=0, maxResults=2000):
        jira_id = jira_obj.key
        click.echo("Processing JIRA: %s" % jira_id)
        
        try:
            issue = asf_jira.issue(jira_id)
            fixVersions = []
            for version in issue.fields.fixVersions:
                fixVersions.append({'name': version.name})
            fixVersions.append({'name': fix_version})
            issue.update(fields={'fixVersions': fixVersions})
        except Exception as e:
            raise ValueError(
                "ASF JIRA could not find issue {}\n{}".format(jira_id, e))
            
def update_jira_issues():
    fix_version = click.prompt(
        click.style(
            "Enter fix version", fg='blue', bold=True),
        default=None)
        
    if fix_version is None:
        raise click.UsageError('No fix version specified')
    
    update_jira_issue(
            fix_version=fix_version)
        

if __name__ == "__main__":
    try:
        update_jira_issues()
    except:
        raise
