#!/usr/bin/env python
#
# Copyright (C) 2011-2014 ABINIT Group (Yann Pouillon)
#
# This file is part of the ABINIT software package. For license information,
# please see the COPYING file in the top-level directory of the ABINIT source
# distribution.
#

from __future__ import print_function

try:
    from configparser import ConfigParser,NoOptionError
except ImportError:
    from ConfigParser import ConfigParser,NoOptionError
from time import gmtime,strftime

import subprocess
import os
import re
import sys

class MyConfigParser(ConfigParser):

  def optionxform(self,option):
    return str(option)

# ---------------------------------------------------------------------------- #

#
# Subroutines
#

# Init macro header
def macro_patches(name,stamp,patches):

  # Create template
  ret = """# Generated by %s on %s

#
# Check whether fallbacks have patches
#

#
# IMPORTANT NOTE
#
# This file has been automatically generated by the %s
# script. If you try to edit it, your changes will systematically be
# overwritten.
#



# AFB_PATCHES_SETUP()
# -------------------
#
# Tells the user which packages have patches.
#
AC_DEFUN([AFB_PATCHES_SETUP],[
@MACRO@]) # AFB_PATCHES_SETUP
""" % (name,stamp,name)

  # List packages with patches
  m4 = ""
  for pkg in patches:
    m4 += "  AC_MSG_NOTICE([will apply the following patches for %s])\n" % pkg
    for fix in patches[pkg]:
      m4 += "  AC_MSG_NOTICE([  * %s])\n" % fix
  if ( len(list(patches.keys())) > 0 ):
    m4 += "\n  AC_CHECK_PROGS([PATCH],[patch])\n"
    m4 += "  if test \"${PATCH}\" = \"\"; then\n"
    m4 += """    AC_MSG_ERROR([patch program not found
        please install it before configuring Abinit Fallbacks])\n"""
    m4 += "  fi\n"

  # Substitute macro
  ret = re.sub("@MACRO@",m4,ret)

  return ret



# ---------------------------------------------------------------------------- #

#
# Main program
#

# Initial setup
my_name    = "make-macros-patches"
my_configs = ["config/specs/fallbacks.conf"]
my_output  = "config/m4/auto-patches.m4"

# Check if we are in the top of the ABINIT source tree
if ( not os.path.exists("configure.ac") or
     not os.path.exists("config/specs/fallbacks.conf") ):
  print("%s: You must be in the top of an ABINIT source tree." % my_name)
  print("%s: Aborting now." % my_name)
  sys.exit(1)

# Read config open(s)
for cnf_file in my_configs:
  if ( os.path.exists(cnf_file) ):
    if ( re.search("\.cf$",cnf_file) ):
      exec(compile(open(cnf_file).read(), cnf_file, 'exec'))
  else:
    print("%s: Could not find config file (%s)." % (my_name,cnf_file))
    print("%s: Aborting now." % my_name)
    sys.exit(2)

# What time is it?
now = strftime("%Y/%m/%d %H:%M:%S +0000",gmtime())

# Init
cnf = MyConfigParser()
cnf.read(my_configs[0])
abinit_fallbacks = cnf.sections()
abinit_fallbacks.sort()
if ( os.path.exists("patches") ):
  patch_list = os.listdir("patches")
else:
  patch_list = []
patch_list.sort()
fbk_patches = {}

# Process fallbacks
for pkg in abinit_fallbacks:

  # Extract mandatory package information
  pkg_name = cnf.get(pkg,"name")
  re_patch = re.compile("%s-[0-9]{4}.patch" % pkg_name)

  # Find patches
  for fix in patch_list:
    if ( re_patch.match(fix) ):
      if ( not pkg_name in fbk_patches ):
        fbk_patches[pkg_name] = []
      fbk_patches[pkg_name].append(fix)

# Write down macro
open(my_output,"w").write(macro_patches(my_name,now,fbk_patches))
