#!/usr/bin/python3

import os
import sys
import re
import argparse
import textwrap
import subprocess
from termcolor import colored

sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/..'))
import opi
from opi.plugins import PluginManager
from opi.version import __version__
from opi.state import global_state


class PreserveWhiteSpaceWrapRawTextHelpFormatter(argparse.RawTextHelpFormatter):
	def __add_whitespace(self, idx, iWSpace, text):
		if idx == 0:
			return text
		return (' ' * iWSpace) + text

	def _split_lines(self, text, width):
		textRows = text.splitlines()
		for idx,line in enumerate(textRows):
			search = re.search('\s*[\d\-]*\.?\s*', line)
			if line.strip() == '':
				textRows[idx] = ' '
			elif search:
				lWSpace = search.end()
				lines = [self.__add_whitespace(i,lWSpace,x) for i,x in enumerate(textwrap.wrap(line, width))]
				textRows[idx] = lines
		return [item for sublist in textRows for item in sublist]


try:
	pm = PluginManager()
	ap = argparse.ArgumentParser(
		formatter_class=PreserveWhiteSpaceWrapRawTextHelpFormatter,
		description=textwrap.dedent('''\
			openSUSE Package Installer
			==========================

			Search and install almost all packages available for openSUSE and SLE:
			  1. openSUSE Build Service
			  2. Packman
			  3. Popular packages for various vendors

		'''),
		epilog=textwrap.dedent('''\
			Also these queries (provided by plugins) can be used to install packages from various other vendors:
		''') + pm.get_plugin_string(' ' * 2))

	ap.add_argument('query', nargs='*', type=str, help=textwrap.dedent('''\
		can be any package name or part of it and will be searched for both at the openSUSE Build Service and Packman.
		If multiple query arguments are provided only results matching all of them are returned.
	'''))
	ap.add_argument('-v', '--version', action='version', version=f'opi version {__version__}')
	ap.add_argument('-n', dest='non_interactive', action='store_true', help="Run in non interactive mode")
	ap.add_argument('-P', dest='no_plugins', action='store_true', help="Don't run any plugins - only search repos, OBS and Packman")

	args = ap.parse_args()

	if not args.query:
		ap.print_help()
		sys.exit()

	if args.non_interactive:
		global_state.arg_non_interactive = True
		if subprocess.run(['sudo', '-n', 'true']).returncode != 0:
			print('Error: In non-interactive mode this command must be run as root')
			print('       or sudo must not require interaction.')
			sys.exit(1)

	if not args.no_plugins:
		# Try to find a matching plugin for the query (and run it and exit afterwards)
		pm.run(args.query[0])

	binaries = []
	binaries.extend(opi.search_published_binary('openSUSE', args.query))
	binaries.extend(opi.search_published_binary('Packman', args.query))
	binaries = opi.sort_uniq_binaries(binaries)
	if len(binaries) == 0:
		print('No package found.')
		sys.exit()

	# Print and select a package name option
	binary_names = opi.get_binary_names(binaries)
	selected_name = opi.ask_for_option(binary_names)
	print('You have selected package name:', selected_name)

	# Inject binaries from local repos
	binaries = opi.search_local_repos(selected_name) + binaries

	binary_options = opi.get_binaries_by_name(selected_name, binaries)

	# Print and select a binary package option
	selected_binary = opi.ask_for_option(binary_options, option_filter=opi.format_binary_option, disable_pager=True)
	print('You have selected binary package:', opi.format_binary_option(selected_binary, table=False))
	if opi.is_personal_project(selected_binary['project']):
		print(colored(
			'BE CAREFUL! The package is from a personal repository and NOT reviewed by others.\n'
			'You can ask the author to submit the package to development projects and openSUSE:Factory.\n'
			'Learn more at https://en.opensuse.org/openSUSE:How_to_contribute_to_Factory',
			'red'
		))
	elif selected_binary['project'] == 'openSUSE:Factory':
		print(opi.colored(
			'BE CAREFUL! You are about to add the Factory Repository.\n'
			'This repo contains the unreleased Tumbleweed distro before openQA tests have been run.\n'
			'Only proceed if you know what you are doing!',
			'yellow'
		))
		if not opi.ask_yes_or_no('Do you want to continue?', default_answer='n'):
			sys.exit()

	# Install selected package
	opi.install_binary(selected_binary)
except KeyboardInterrupt:
	print()
