#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Travis CI Scripts
# Copyright (C) 2018-2022 by Thomas Dreibholz
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Contact: dreibh@iem.uni-due.de


import glob
import os
import re
import subprocess
import sys


# ###### Extract dependencies ###############################################
depLine = re.compile(r'^(.*:[ \t]*)(.*)$')
depItem = re.compile(r'^([a-zA-Z0-9-+\.]+)[\s]*(|\|.*|\(.*)[\s]*$')

def extractDependencies(line, system):
   dependencies = []

   # Remove "build-depends:", etc.:
   m = depLine.match(line)
   if m != None:
      line = m.group(2)
   line = line.strip()

   # Split into segments
   for l in line.split(','):
      l = l.strip()
      m = depItem.match(l)
      if m != None:
         dependency = m.group(1)

         # ------ Ugly work-around for cmake --------------------------------
         # We need cmake >= 3.0!
         if ((dependency == 'cmake') or (dependency == 'cmake3')):
            if ((system == 'debian') or (system == 'ubuntu')):
               try:
                  distribution = subprocess.check_output( ["lsb_release", "-cs"] ).decode('utf-8').strip()
                  # print("distribution=", distribution, ".")
                  if distribution in [ 'trusty' ]:
                     dependency = 'cmake3'
               except:
                  pass

         dependencies.append(dependency)

   return dependencies


# ###### Main program #######################################################

# ====== Check arguments ====================================================
if len(sys.argv) < 2:
   sys.stderr.write('Usage: ' + sys.argv[0] + ' debian|ubuntu|fedora|freebsd [-i|--install]\n')
   sys.exit(1)
system     = sys.argv[1]
runInstall = False
for i in range(2, len(sys.argv)):
   if sys.argv[i] == '-i' or sys.argv[i] == '--install':
      runInstall = True
   else:
      sys.stderr.write('ERROR: Bad parameter ' + sys.argv[i] + '!')
      sys.exit(1)

# ====== Debian/Ubuntu ======================================================
dependencies = [ ]
if ((system == 'debian') or  (system == 'ubuntu')):
   if os.path.exists('debian/control'):
      with open('debian/control', 'r') as fp:
         inside = False
         for line in fp:
            if not line:
               break
            line_lower = line.lower()
            if inside:
               if line.startswith((' ', "\t")):
                  dependencies = dependencies + extractDependencies(line, system)
                  continue
               elif line.startswith('#'):
                  continue
               inside = False
            if line_lower.startswith(('build-depends:', 'build-depends-indep:')):
               dependencies = dependencies + extractDependencies(line, system)
               inside = True

      for dependency in sorted(set(dependencies)):
          sys.stdout.write(dependency + ' ')
      sys.stdout.write('\n')

      if runInstall == True:
         subprocess.call([ 'apt-get', 'install', '-y' ] + dependencies)

   else:
      sys.stderr.write('ERROR: Unable to locate Debian control file!\n')
      sys.exit(1)


# ====== Fedora =============================================================
elif system == 'fedora':
   specFiles = glob.glob('rpm/*.spec')
   if len(specFiles) == 1:
      with open(specFiles[0], 'r') as fp:
         inside = False
         for line in fp:
            if not line:
               break
            line_lower = line.lower()
            if inside:
               if line.startswith((' ', "\t")):
                  dependencies = dependencies + extractDependencies(line, system)
                  continue
               elif line.startswith('#'):
                  continue
               inside = False
            if line_lower.startswith('buildrequires:'):
               dependencies = dependencies + extractDependencies(line, system)
               inside = True

      for dependency in sorted(set(dependencies)):
          sys.stdout.write(dependency + ' ')
      sys.stdout.write('\n')

      if runInstall == True:
         subprocess.call([ 'dnf', 'install', '-y' ] + dependencies)

   else:
      sys.stderr.write('ERROR: Unable to locate RPM spec file!\n')
      sys.exit(1)


# ====== FreeBSD ============================================================
elif system == 'freebsd':
   freeBSDMakefile = glob.glob('freebsd/*/Makefile')
   if len(freeBSDMakefile) == 1:
      freeBSDDirectory = os.path.dirname(freeBSDMakefile[0])

      cmd = 'make build-depends-list && make run-depends-list'
      try:
         os.chdir(freeBSDDirectory)
         output = subprocess.check_output(cmd, shell=True)
      except Exception as e:
         sys.stderr.write('ERROR: Getting FreeBSD dependencies failed: ' + str(e) + '\n')
         sys.exit(1)

      if output != None:
         ports = output.decode('utf-8').splitlines()
         for port in ports:
            basename = os.path.basename(port)
            if basename == 'glib20':
               basename = 'glib'   # May be there is a better solution here?
            dependencies.append(basename)

      for dependency in sorted(set(dependencies)):
          sys.stdout.write(dependency + ' ')
      sys.stdout.write('\n')

      if runInstall == True:
         subprocess.call([ 'pkg', 'install', '-y' ] + dependencies)

   else:
      sys.stderr.write('ERROR: Unable to locate FreeBSD port makefile!\n')
      sys.exit(1)


# ====== Error ==============================================================
else:
   sys.stderr.write('ERROR: Invalid system name "' + system + '"!\n')
   sys.exit(1)
