#!/usr/bin/python
#   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 re
import sys
from optparse import OptionParser
import httplib
import urllib
import cgi
try:
  import json
except ImportError:
  import simplejson as json


namePattern = re.compile(r' \([0-9]+\)')

def clean(str):
  return quoteHtml(re.sub(namePattern, "", str))

def formatComponents(str):
  str = re.sub(namePattern, '', str).replace("'", "")
  if str != "":
    ret = "(" + str + ")"
  else:
    ret = ""
  return quoteHtml(ret)
    
def quoteHtml(str):
  return cgi.escape(str).encode('ascii', 'xmlcharrefreplace')

def mstr(obj):
  if (obj == None):
    return ""
  return unicode(obj)

class Version:
  """Represents a version number"""
  def __init__(self, data):
    self.mod = False
    self.data = data
    found = re.match('^((\d+)(\.\d+)*).*$', data)
    if (found):
      self.parts = [ int(p) for p in found.group(1).split('.') ]
    else:
      self.parts = []
    # backfill version with zeroes if missing parts
    self.parts.extend((0,) * (3 - len(self.parts)))

  def decBugFix(self):
    self.mod = True
    self.parts[2] -= 1
    return self

  def __str__(self):
    if (self.mod):
      return '.'.join([ str(p) for p in self.parts ])
    return self.data

  def __cmp__(self, other):
    return cmp(self.parts, other.parts)

class Jira:
  """A single JIRA"""

  def __init__(self, data, parent):
    self.key = data['key']
    self.fields = data['fields']
    self.parent = parent
    self.notes = None

  def getId(self):
    return mstr(self.key)

  def getDescription(self):
    return mstr(self.fields['description'])

  def getReleaseNote(self):
    if (self.notes == None):
      field = self.parent.fieldIdMap['Release Note']
      if (self.fields.has_key(field)):
        self.notes=mstr(self.fields[field])
      else:
        self.notes=self.getDescription()
    return self.notes

  def getPriority(self):
    ret = ""
    pri = self.fields['priority']
    if(pri != None):
      ret = pri['name']
    return mstr(ret)

  def getAssignee(self):
    ret = ""
    mid = self.fields['assignee']
    if(mid != None):
      ret = mid['displayName']
    return mstr(ret)

  def getComponents(self):
    return " , ".join([ comp['name'] for comp in self.fields['components'] ])

  def getSummary(self):
    return self.fields['summary']

  def getType(self):
    ret = ""
    mid = self.fields['issuetype']
    if(mid != None):
      ret = mid['name']
    return mstr(ret)

  def getReporter(self):
    ret = ""
    mid = self.fields['reporter']
    if(mid != None):
      ret = mid['displayName']
    return mstr(ret)

  def getProject(self):
    ret = ""
    mid = self.fields['project']
    if(mid != None):
      ret = mid['key']
    return mstr(ret)



class JiraIter:
  """An Iterator of JIRAs"""

  def __init__(self, versions):
    self.versions = versions

    resp = urllib.urlopen("https://issues.apache.org/jira/rest/api/2/field")
    data = json.loads(resp.read())

    self.fieldIdMap = {}
    for part in data:
      self.fieldIdMap[part['name']] = part['id']

    self.jiras = []
    at=0
    end=1
    count=100
    while (at < end):
      params = urllib.urlencode({'jql': "project in (HADOOP,HDFS,MAPREDUCE,YARN) and fixVersion in ('"+"' , '".join(versions)+"') and resolution = Fixed", 'startAt':at+1, 'maxResults':count})
      resp = urllib.urlopen("https://issues.apache.org/jira/rest/api/2/search?%s"%params)
      data = json.loads(resp.read())
      if (data.has_key('errorMessages')):
        raise Exception(data['errorMessages'])
      at = data['startAt'] + data['maxResults']
      end = data['total']
      self.jiras.extend(data['issues'])

    self.iter = self.jiras.__iter__()

  def __iter__(self):
    return self

  def next(self):
    data = self.iter.next()
    j = Jira(data, self)
    return j

class Outputs:
  """Several different files to output to at the same time"""

  def __init__(self, base_file_name, file_name_pattern, keys, params={}):
    self.params = params
    self.base = open(base_file_name%params, 'w')
    self.others = {}
    for key in keys:
      both = dict(params)
      both['key'] = key
      self.others[key] = open(file_name_pattern%both, 'w')

  def writeAll(self, pattern):
    both = dict(self.params)
    both['key'] = ''
    self.base.write(pattern%both)
    for key in self.others.keys():
      both = dict(self.params)
      both['key'] = key
      self.others[key].write(pattern%both)

  def writeKeyRaw(self, key, str):
    self.base.write(str)
    if (self.others.has_key(key)):
      self.others[key].write(str)
  
  def close(self):
    self.base.close()
    for fd in self.others.values():
      fd.close()

def main():
  parser = OptionParser(usage="usage: %prog [options] [USER-ignored] [PASSWORD-ignored] [VERSION]")
  parser.add_option("-v", "--version", dest="versions",
             action="append", type="string", 
             help="versions in JIRA to include in releasenotes", metavar="VERSION")
  parser.add_option("--previousVer", dest="previousVer",
             action="store", type="string", 
             help="previous version to include in releasenotes", metavar="VERSION")

  (options, args) = parser.parse_args()

  if (options.versions == None):
    options.versions = []

  if (len(args) > 2):
    options.versions.append(args[2])

  if (len(options.versions) <= 0):
    parser.error("At least one version needs to be supplied")

  versions = [ Version(v) for v in options.versions];
  versions.sort();

  maxVersion = str(versions[-1])
  if(options.previousVer == None):  
    options.previousVer = str(versions[0].decBugFix())
    print >> sys.stderr, "WARNING: no previousVersion given, guessing it is "+options.previousVer

  list = JiraIter(options.versions)
  version = maxVersion
  outputs = Outputs("releasenotes.%(ver)s.html", 
    "releasenotes.%(key)s.%(ver)s.html", 
    ["HADOOP","HDFS","MAPREDUCE","YARN"], {"ver":maxVersion, "previousVer":options.previousVer})

  head = '<META http-equiv="Content-Type" content="text/html; charset=UTF-8">\n' \
    '<title>Hadoop %(key)s %(ver)s Release Notes</title>\n' \
    '<STYLE type="text/css">\n' \
    '	H1 {font-family: sans-serif}\n' \
    '	H2 {font-family: sans-serif; margin-left: 7mm}\n' \
    '	TABLE {margin-left: 7mm}\n' \
    '</STYLE>\n' \
    '</head>\n' \
    '<body>\n' \
    '<h1>Hadoop %(key)s %(ver)s Release Notes</h1>\n' \
    'These release notes include new developer and user-facing incompatibilities, features, and major improvements. \n' \
    '<a name="changes"/>\n' \
    '<h2>Changes since Hadoop %(previousVer)s</h2>\n' \
    '<ul>\n'

  outputs.writeAll(head)

  for jira in list:
    line = '<li> <a href="https://issues.apache.org/jira/browse/%s">%s</a>.\n' \
      '     %s %s reported by %s and fixed by %s %s<br>\n' \
      '     <b>%s</b><br>\n' \
      '     <blockquote>%s</blockquote></li>\n' \
      % (quoteHtml(jira.getId()), quoteHtml(jira.getId()), clean(jira.getPriority()), clean(jira.getType()).lower(),
         quoteHtml(jira.getReporter()), quoteHtml(jira.getAssignee()), formatComponents(jira.getComponents()),
         quoteHtml(jira.getSummary()), quoteHtml(jira.getReleaseNote()))
    outputs.writeKeyRaw(jira.getProject(), line)
 
  outputs.writeAll("</ul>\n</body></html>\n")
  outputs.close()

if __name__ == "__main__":
  main()

