#!/usr/bin/python3
SVER = '2.0.15'
##############################################################################
# sagvc - Security Announcement Patterns Change Log Generator
# Copyright (C) 2023 SUSE LLC
#
# Description:  Creates a list of new security announcement pattern entries
#               for the change log
# Modified:     2023 Aug 25
#
##############################################################################
#
#  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; version 2 of the License.
#
#  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/>.
#
#  Authors/Contributors:
#     Jason Record <jason.record@suse.com>
#
##############################################################################

import sys
import os
import re
import getopt
import datetime
import signal
import configparser
import patdevel as pd

##############################################################################
# Global Options
##############################################################################

title_string = "Security Advisory Change Log Generator"

##############################################################################
# Functions
##############################################################################

def usage():
	"Displays usage information"
	display = "  {:33s} {}"
	print("Usage: sagvc [options] [Date]")
	print()
	print("Options:")
	print(display.format("-h, --help", "Display this help"))
	print(display.format('-r <dir>, --repo <dir>', "Set the path to a GitHub repository directory"))
	print(display.format('-a, --all', "Generate change logs from all GitHub repository directories"))
	print(display.format('-l <level>, --log_level <level>', "Set log level, default: Minimal"))
	print(display.format('', "0 Quiet, 1 Minimal, 2 Normal, 3 Verbose, 4 Debug"))
	print()

def signal_handler(sig, frame):
	print("\n\nAborting...\n")
	sys.exit(1)

def generate_sa_change_log(_git_repo, _given_date):
	SAID_WIDTH = 5
	saids = []
	pattern_list = _git_repo.get_local_sa_patterns()
	date_updated = pd.convert_log_date(_given_date, use_prev_month=True)
	count = 0
	if( len(pattern_list) > 0 ):
		data = _git_repo.get_info()
		print()
		for this_pattern in pattern_list:
			parts = this_pattern.split('_')
			said = ":".join([parts[-4], parts[-3]])
			saids.append(said)
		count = len(saids)
		print("- Changes in version " + str(data['spec_ver_bumped']))
		print("  - New security announcement patterns as of " + date_updated + " (" + str(count) + "):")
		for x in range(0, len(saids), SAID_WIDTH):
			row = saids[x:x+SAID_WIDTH]
			print("    " + " ".join(row))
		print("\nNew security announcement patterns as of " + date_updated + " - " + str(count))
	else:
		print("Warning: No security patterns found for the change log")
	print()

def generate_all_sa_change_logs(msg, config, given_date):
	repo_dir = pd.config_entry(config.get("Common", "sca_repo_dir"), '/')
	repo_list = pd.config_entry(config.get("GitHub", "patdev_repos")).split(',')
	pd.check_git_repos(config, msg)
	current_log_level = msg.get_level()
	for repo in repo_list:
		if current_log_level > msg.LOG_MIN:
			pd.separator_line('-')
		path = repo_dir + repo
		git_repo = pd.GitHubRepository(msg, path)
		patterns = len(git_repo.get_local_sa_patterns())
		if( msg.get_level() >= msg.LOG_NORMAL ):
			msg.min("Repository location", path)
			generate_sa_change_log(git_repo, given_date)
		else:
			if patterns > 0:
				pd.separator_line('-')
				msg.min("Repository location", path)
				generate_sa_change_log(git_repo, given_date)

##############################################################################
# Main
##############################################################################

def main(argv):
	"main entry point"
	global SVER
	parse_patterns = []
	given_dir = ''
	force_all = False
	
	if( os.path.exists(pd.config_file) ):
		config.read(pd.config_file)
		config_log_level = pd.config_entry(config.get("Common", "log_level"))
		config_logging = msg.validate_level(config_log_level)
		if( config_logging >= msg.LOG_QUIET ):
			msg.set_level(config_logging)
		else:
			msg.min("Warning: Invalid log level in config file, using instance default")
	else:
		pd.title(title_string, SVER)
		print("Error: Config file not found - {}".format(pd.config_file))
		print()
		sys.exit(1)

	try:
		(optlist, args) = getopt.gnu_getopt(argv[1:], "hr:al:", ["help", "repo=", "all", "log_level="])
	except getopt.GetoptError as exc:
		pd.title(title_string, SVER)
		print("Error:", exc, file=sys.stderr)
		sys.exit(2)
	for opt, arg in optlist:
		if opt in {"-h", "--help"}:
			pd.title(title_string, SVER)
			usage()
			sys.exit(0)
		elif opt in {"-r", "--repo"}:
			given_dir = arg
			if not os.path.isdir(given_dir):
				pd.title(title_string, SVER)
				print("Error: Directory not found - {}".format(given_dir))
				usage()
				sys.exit(1)
		elif opt in {"-a", "--all"}:
			force_all = True
		elif opt in {"-l", "--log_level"}:
			user_logging = msg.validate_level(arg)
			if( user_logging >= msg.LOG_QUIET ):
				msg.set_level(user_logging)
			else:
				print("Warning: Invalid log level, using instance default")

	if( msg.get_level() > msg.LOG_QUIET ):
		pd.title(title_string, SVER)

	msg.normal("Log Level", msg.get_level_str())

	if len(args) > 0: # A path to a proposed GitHub repository was given on the command line
		given_date = '-'.join(args)
	else:
		given_date = ''

	if force_all:
		msg.debug("  <conf> Force using GitHub directories", "Config File")
		generate_all_sa_change_logs(msg, config, given_date)
	else:
		if( len(given_dir) > 0 ):
			path = os.path.abspath(given_dir)
			msg.debug("  <arg> GitHub directory given", path)
			if pd.github_path_valid(msg, path):
				pd.separator_line('-')
				msg.min("Repository location", path)
				git_repo = pd.GitHubRepository(msg, path)
				generate_sa_change_log(git_repo, given_date)
			else:
				msg.min("Invalid GitHub repository", path)
				sys.exit(4)

		else: # No repository path given on the command line
			path = os.getcwd()
			msg.debug("  <cwd> GitHub directory given", path)
			if pd.github_path_valid(msg, path):
				pd.separator_line('-')
				msg.min("Repository location", path)
				git_repo = pd.GitHubRepository(msg, path)
				generate_sa_change_log(git_repo, given_date)
			else:
				msg.debug("  <conf> GitHub directories", pd.config_file)
				generate_all_sa_change_logs(msg, config, given_date)

# Entry point
if __name__ == "__main__":
	signal.signal(signal.SIGINT, signal_handler)
	config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
	msg = pd.DisplayMessages()
	main(sys.argv)

