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

import argparse
import io
import os
import re
import subprocess
import sys

class Version(object):
  def __init__(self, major, minor, bugfix):
    self.major = major
    self.minor = minor
    self.bugfix = bugfix
    self.previous_dot_matcher = self.make_previous_matcher()
    self.dot = '%d.%d.%d' % (self.major, self.minor, self.bugfix) 
    self.constant = 'LUCENE_%d_%d_%d' % (self.major, self.minor, self.bugfix)

  @classmethod
  def parse(cls, value):
    match = re.search(r'(\d+)\.(\d+).(\d+)', value) 
    if match is None:
      raise argparse.ArgumentTypeError('Version argument must be of format x.y.z')
    return Version(*[int(v) for v in match.groups()])

  def __str__(self):
    return self.dot

  def make_previous_matcher(self, prefix='', suffix='', sep='\\.'):
    if self.is_bugfix_release():
      pattern = '%s%s%s%s%d' % (self.major, sep, self.minor, sep, self.bugfix - 1)
    elif self.is_minor_release():
      pattern = '%s%s%d%s\\d+' % (self.major, sep, self.minor - 1, sep)
    else:
      pattern = '%d%s\\d+%s\\d+' % (self.major - 1, sep, sep)

    return re.compile(prefix + '(' + pattern + ')' + suffix)

  def is_bugfix_release(self):
    return self.bugfix != 0

  def is_minor_release(self):
    return self.bugfix == 0 and self.minor != 0

  def is_major_release(self):
    return self.bugfix == 0 and self.minor == 0

def run(cmd):
  try:
    subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
  except subprocess.CalledProcessError as e:
    print(e.output.decode('utf-8'))
    raise e

def update_file(filename, line_re, edit):
  infile = open(filename, 'r')
  buffer = [] 
  
  changed = False
  for line in infile:
    if not changed:
      match = line_re.search(line)
      if match:
        changed = edit(buffer, match, line)
        if changed is None:
          return False
        continue
    buffer.append(line)
  if not changed:
    raise Exception('Could not find %s in %s' % (line_re, filename))
  with open(filename, 'w') as f:
    f.write(''.join(buffer))
  return True

def update_changes(filename, new_version):
  print('  adding new section to %s...' % filename, end='')
  matcher = re.compile(r'\d+\.\d+\.\d+\s+===')
  def edit(buffer, match, line):
    if new_version.dot in line:
      return None
    match = new_version.previous_dot_matcher.search(line)
    if match is not None:
      buffer.append(line.replace(match.group(0), new_version.dot))
      buffer.append('(No Changes)\n\n')
    buffer.append(line)
    return match is not None
     
  changed = update_file(filename, matcher, edit)
  print('done' if changed else 'uptodate')

def add_constant(new_version, deprecate):
  filename = 'lucene/core/src/java/org/apache/lucene/util/Version.java'
  print('  adding constant %s...' % new_version.constant, end='')
  constant_prefix = 'public static final Version LUCENE_'
  matcher = re.compile(constant_prefix)
  prev_matcher = new_version.make_previous_matcher(prefix=constant_prefix, sep='_')

  def ensure_deprecated(buffer):
    last = buffer[-1]
    if last.strip() != '@Deprecated':
      spaces = ' ' * (len(last) - len(last.lstrip()) - 1)
      buffer[-1] = spaces + (' * @deprecated (%s) Use latest\n' % new_version)
      buffer.append(spaces + ' */\n')
      buffer.append(spaces + '@Deprecated\n')

  def buffer_constant(buffer, line):
    spaces = ' ' * (len(line) - len(line.lstrip()))
    buffer.append('\n' + spaces + '/**\n')
    buffer.append(spaces + ' * Match settings and bugs in Lucene\'s %s release.\n' % new_version)
    if deprecate:
      buffer.append(spaces + ' * @deprecated Use latest\n')
    buffer.append(spaces + ' */\n')
    if deprecate:
      buffer.append(spaces + '@Deprecated\n')
    buffer.append(spaces + 'public static final Version %s = new Version(%d, %d, %d);\n' %
                  (new_version.constant, new_version.major, new_version.minor, new_version.bugfix))
  
  class Edit(object):
    found = -1
    def __call__(self, buffer, match, line):
      if new_version.constant in line:
        return None # constant already exists
      # outter match is just to find lines declaring version constants
      match = prev_matcher.search(line)
      if match is not None:
        ensure_deprecated(buffer) # old version should be deprecated
        self.found = len(buffer) + 1 # extra 1 for buffering current line below
      elif self.found != -1:
        # we didn't match, but we previously had a match, so insert new version here
        # first find where to insert (first empty line before current constant)
        c = []
        buffer_constant(c, line)
        tmp = buffer[self.found:]
        buffer[self.found:] = c
        buffer.extend(tmp)
        buffer.append(line)
        return True

      buffer.append(line)
      return False
  
  changed = update_file(filename, matcher, Edit())
  print('done' if changed else 'uptodate')

version_prop_re = re.compile('version\.base=(.*)')
def update_build_version(new_version):
  print('  changing version.base...', end='')
  filename = 'lucene/version.properties'
  def edit(buffer, match, line):
    if new_version.dot in line:
      return None
    buffer.append('version.base=' + new_version.dot + '\n')
    return True 

  changed = update_file(filename, version_prop_re, edit)
  print('done' if changed else 'uptodate')

def update_latest_constant(new_version):
  print('  changing Version.LATEST to %s...' % new_version.constant, end='')
  filename = 'lucene/core/src/java/org/apache/lucene/util/Version.java'
  matcher = re.compile('public static final Version LATEST')
  def edit(buffer, match, line):
    if new_version.constant in line:
      return None
    buffer.append(line.rpartition('=')[0] + ('= %s;\n' % new_version.constant))
    return True

  changed = update_file(filename, matcher, edit)
  print('done' if changed else 'uptodate')
  
def update_example_solrconfigs(new_version):
  print('  updating example solrconfig.xml files')
  matcher = re.compile('<luceneMatchVersion>')

  for root,dirs,files in os.walk('solr/example'):
    for f in files:
      if f == 'solrconfig.xml':
        update_solrconfig(os.path.join(root, f), matcher, new_version) 

def update_solrconfig(filename, matcher, new_version):
  print('    %s...' % filename, end='')
  def edit(buffer, match, line):
    if new_version.dot in line:
      return None
    match = new_version.previous_dot_matcher.search(line)
    if match is None:
      return False
    buffer.append(line.replace(match.group(1), new_version.dot))
    return True

  changed = update_file(filename, matcher, edit)
  print('done' if changed else 'uptodate')

def codec_exists(version):
  codecs_dir = 'lucene/core/src/java/org/apache/lucene/codecs'
  codec_file = '%(dir)s/lucene%(x)s%(y)s/Lucene%(x)s%(y)sCodec.java'
  return os.path.exists(codec_file % {'x': version.major, 'y': version.minor, 'dir': codecs_dir})

def create_backcompat_indexes(version, on_trunk):
  majorminor = '%d%d' % (version.major, version.minor)
  codec = 'Lucene%s' % majorminor
  backcompat_dir = 'lucene/backwards-codecs' if on_trunk else 'lucene/core'

  create_index(codec, backcompat_dir, 'cfs', majorminor)
  create_index(codec, backcompat_dir, 'nocfs', majorminor)

def create_index(codec, codecs_dir, type, majorminor):
  filename = 'index.%s.%s.zip' % (majorminor, type)
  print('  creating %s...' % filename, end='')
  index_dir = 'src/test/org/apache/lucene/index'
  if os.path.exists(os.path.join(codecs_dir, index_dir, filename)):
    print('uptodate')
    return

  test = {'cfs': 'testCreateCFS', 'nocfs': 'testCreateNonCFS'}[type]
  ant_args = ' '.join([
    '-Dtests.codec=%s' % codec,
    '-Dtests.useSecurityManager=false',
    '-Dtestcase=CreateBackwardsCompatibilityIndex',
    '-Dtestmethod=%s' % test
  ])
  base_dir = os.getcwd()
  bc_index_dir = '/tmp/idx/index.%s' % type
  bc_index_file = os.path.join(bc_index_dir, filename)
  
  success = False
  if not os.path.exists(bc_index_file):
    os.chdir(codecs_dir)
    run('ant test %s' % ant_args)
    os.chdir('/tmp/idx/index.%s' % type)
    run('zip %s *' % filename)
  run('cp %s %s' % (bc_index_file, os.path.join(base_dir, codecs_dir, index_dir)))
  os.chdir(base_dir)
  run('svn add %s' % os.path.join(codecs_dir, index_dir, filename))
  success = True

  os.chdir(base_dir)
  run('rm -rf %s' % bc_index_dir)
  if success:
    print('done')

def update_backcompat_tests(version, on_trunk):
  majorminor = '%d%d' % (version.major, version.minor)
  print('  adding new indexes to backcompat tests...', end='')
  basedir = 'lucene/backwards-codecs' if on_trunk else 'lucene/core'
  filename = '%s/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java' % basedir
  matcher = re.compile(r'final static String\[\] oldNames = {|};')
  cfs_name = '%s.cfs' % majorminor
  nocfs_name = '%s.nocfs' % majorminor

  class Edit(object):
    start = None
    def __call__(self, buffer, match, line):
      if self.start:
        # first check if the indexes we are adding already exist      
        last_ndx = len(buffer) - 1 
        i = last_ndx
        while i >= self.start:
          if cfs_name in buffer[i]:
            return None
          i -= 1

        last = buffer[last_ndx]
        spaces = ' ' * (len(last) - len(last.lstrip()))
        quote_ndx = last.find('"')
        quote_ndx = last.find('"', quote_ndx + 1)
        buffer[last_ndx] = last[:quote_ndx + 1] + "," + last[quote_ndx + 1:]
        buffer.append(spaces + ('"%s",\n' % cfs_name))
        buffer.append(spaces + ('"%s"\n' % nocfs_name))
        buffer.append(line)
        return True

      if 'oldNames' in line:
        self.start = len(buffer) # location of first index name
      buffer.append(line)
      return False
        
  changed = update_file(filename, matcher, Edit())
  print('done' if changed else 'uptodate')

def check_lucene_version_tests():
  print('  checking lucene version tests...', end='')
  base_dir = os.getcwd()
  os.chdir('lucene/core') 
  run('ant test -Dtestcase=TestVersion')
  os.chdir(base_dir)
  print('ok')

def check_solr_version_tests():
  print('  checking solr version tests...', end='')
  base_dir = os.getcwd()
  os.chdir('solr/core') 
  run('ant test -Dtestcase=TestLuceneMatchVersion')
  os.chdir(base_dir)
  print('ok')

def check_backcompat_tests(on_trunk):
  print('  checking backcompat tests...', end='')
  base_dir = os.getcwd()
  basedir = 'lucene/backwards-codecs' if on_trunk else 'lucene/core'
  os.chdir(basedir) 
  run('ant test -Dtestcase=TestBackwardsCompatibility')
  os.chdir(base_dir)
  print('ok')

# branch types are "release", "stable" and "trunk"
def find_branch_type():
  output = subprocess.check_output('svn info', shell=True)
  for line in output.split(b'\n'):
    if line.startswith(b'URL:'):
      url = line.split(b'/')[-1]
      break
  else:
    raise Exception('svn info missing repo URL')

  if url == b'trunk':
    return 'trunk'
  if url.startswith(b'branch_'):
    return 'stable'
  if url.startswith(b'lucene_solr_'):
    return 'release'
  raise Exception('Cannot run bumpVersion.py on feature branch')

def find_previous_version():
  return version_prop_re.search(open('lucene/version.properties').read()).group(1)

def merge_change(changeid, repo):
  print('\nMerging downstream change %d...' % changid, end='')
  run('svn merge -c %d --record-only %s' % (changeid, repo))
  print('done')

def read_config():
  parser = argparse.ArgumentParser(description='Add a new version')
  parser.add_argument('version', type=Version.parse)
  parser.add_argument('-c', '--changeid', type=int, help='SVN ChangeId for downstream version change to merge')
  parser.add_argument('-r', '--downstream-repo', help='Path to downstream checkout for given changeid')
  c = parser.parse_args()

  c.branch_type = find_branch_type()
  c.matching_branch = c.version.is_bugfix_release() and c.branch_type == 'release' or \
                      c.version.is_minor_release() and c.branch_type == 'stable' or \
                      c.branch_type == 'major'

  if c.matching_branch:
    c.previous_version = Version.parse(find_previous_version())
  elif c.version.is_minor_release():
    c.previous_version = Version(c.version.major, c.version.minor - 1, 0)
  elif c.version.is_bugfix_release():
    c.previous_version = Version(c.version.major, c.version.minor, c.version.bugfix - 1)

  if bool(c.changeid) != bool(c.downstream_repo):
    parser.error('--changeid and --upstream-repo must be used together')
  if not c.changeid and not c.matching_branch:
    parser.error('Must use --changeid for forward porting bugfix release version to other branches')
  if c.changeid and c.matching_branch:
    parser.error('Cannot use --changeid on branch that new version will originate on')
  if c.changeid and c.version.is_major_release():
    parser.error('Cannot use --changeid for major release')

  return c
  
def main():
  c = read_config() 

  if c.changeid:
    merge_change(c.changeid, c.downstream_repo)  

  print('\nAdding new version %s' % c.version)
  update_changes('lucene/CHANGES.txt', c.version)
  update_changes('solr/CHANGES.txt', c.version)
  add_constant(c.version, not c.matching_branch) 

  if not c.changeid:
    print('\nUpdating latest version')
    update_build_version(c.version)
    update_latest_constant(c.version)
    update_example_solrconfigs(c.version)

  run_backcompat_tests = False
  on_trunk = c.branch_type == 'trunk'
  if not c.version.is_bugfix_release() and codec_exists(c.previous_version):
    print('\nCreating backwards compatibility tests')
    create_backcompat_indexes(c.previous_version, on_trunk)
    update_backcompat_tests(c.previous_version, on_trunk)
    run_backcompat_tests = True

  if c.version.is_major_release():
    print('\nTODO: ')
    print('  - Update major version bounds in Version.java')
    print('  - Move backcompat oldIndexes to unsupportedIndexes in TestBackwardsCompatibility')
    print('  - Update IndexFormatTooOldException throw cases')
  else:
    print('\nTesting changes')
    check_lucene_version_tests()
    check_solr_version_tests()
    if run_backcompat_tests: 
      check_backcompat_tests(on_trunk)

  print()

if __name__ == '__main__':
  try:
    main()
  except KeyboardInterrupt:
    print('\nReceived Ctrl-C, exiting early')
