module main

import (
	http
	os
	json
)

const (
	//url = 'http://localhost:8089'
	url = 'https://vpm.best'
	valid_vpm_commands = ['help', 'search', 'install', 'update', 'remove']
)

struct Mod {
	id int
	name string
	url string
	nr_downloads int
}

fn main() {
	ensure_vmodules_dir_exist()
	change_to_vmodules_dir()
	// This tool is intended to be launched by the v frontend,
	// so its first argument is the path to the v frontend executable.
	args := os.args // args are: vpm vexepath SUBCOMMAND module names
	if args.len < 3 {
		vpm_help([]string)
		exit(5)
	}
	vpm_command := args[2]
	module_names := args[3..]
	//println('module names: ') println(module_names)
	match vpm_command {
		'help'    { vpm_help(module_names) }
		'search'  { vpm_search(module_names) }
		'install' { vpm_install(module_names) }
		'update'  { vpm_update(module_names) }
		'remove'  { vpm_remove(module_names) }
		else {
			println('Error: you tried to run "v $vpm_command"')
			println('... but the v package management tool vpm only knows about these commands:')
			for validcmd in valid_vpm_commands {
				println('    v $validcmd')
			}
			exit(3)
		}
	}
}

fn vpm_search(module_names []string){
	if user_asks_for_help(module_names) {
		println('Usage:')
		println('  v search keyword1 [keyword2] [...]')
		println('  ^^^^^^^^^^^^^^^^^ will search https://vpm.vlang.io/ for matching modules,')
		println('                    and will show details about them')
		exit(0)
	}
	if module_names.len == 0 {
		println('  v search requires *at least one* keyword')
		exit(2)
	}
	todo('search')
}

fn vpm_install(module_names []string){
	if user_asks_for_help(module_names) {
		println('Usage:')
		println('  v install module [module] [module] [...]')
		println('  ^^^^^^^^^^^^^ will install the modules you specified')
		exit(0)
	}
	if module_names.len == 0 {
		println('  v install requires *at least one* module name')
		exit(2)
	}

	mut errors := 0
	for name in module_names {
		modurl := url + '/jsmod/$name'
		r := http.get(modurl) or { panic(err) }

		if r.status_code == 404 {
			println('Skipping module "$name", since $url reported that "$name" does not exist.')
			errors++
			continue
		}

		if r.status_code != 200 {
			println('Skipping module "$name", since $url responded with $r.status_code http status code. Please try again later.')
			errors++
			continue
		}

		s := r.text
		mod := json.decode(Mod, s) or {
			errors++
			println('Skipping module "$name", since its information is not in json format.')
			continue
		}

		if( '' == mod.url || '' == mod.name ){
			errors++
			// a possible 404 error, which means a missing module?
			println('Skipping module "$name", since it is missing name or url information.')
			continue
		}

		final_module_path := get_vmodules_dir_path() + '/' + mod.name.replace('.', '/')

		println('Installing module "$name" from $mod.url to $final_module_path ...')
		_ = os.exec('git clone --depth=1 $mod.url $final_module_path') or {
			errors++
			println('Could not install module "$name" to "$final_module_path" .')
			println('Error details: $err')
			continue
		}
	}
	if errors > 0 {
		exit(1)
	}
}

fn vpm_update(module_names []string){
	if user_asks_for_help(module_names) {
		println('Usage: ')
		println(' a) v update module [module] [module] [...]')
		println('    ^^^^^^^^^^^^ will update the listed modules to their latest versions')
		println(' b) v update')
		println('    ^^^^^^^^^^^^ will update ALL installed modules to their latest versions')
		exit(0)
	}
	todo('update')
}

fn vpm_remove(module_names []string){
	if user_asks_for_help(module_names) {
		println('Usage: ')
		println(' a) v remove module [module] [module] [...]')
		println('    ^^^^^^^^^^^^ will remove the listed modules')
		println(' b) v remove')
		println('    ^^^^^^^^^^^^ will remove ALL installed modules')
		exit(0)
	}
	todo('remove')
}

fn get_vmodules_dir_path() string {
	return os.home_dir() + '.vmodules'
}

fn ensure_vmodules_dir_exist() {
	home_vmodules := get_vmodules_dir_path()
	if !os.dir_exists( home_vmodules ) {
		println('Creating $home_vmodules/ ...')
		os.mkdir(home_vmodules)
	}
}

fn change_to_vmodules_dir() {
	os.chdir(get_vmodules_dir_path())
}

fn todo(vpm_command string){
	println('TODO: v $vpm_command')
	exit(4)
}

fn user_asks_for_help(module_names []string) bool {
	return ('-h' in module_names) || ('--help' in module_names) || ('help' in module_names)
}

fn vpm_help(module_names []string){
	println('Usage:')
	println('  b) v search keyword1 [keyword2] [...]')
	println('  c) v install module [module] [module] [...]')
	println('  d) v update [module] [...]')
	println('  e) v remove [module] [...]')
	println('')
	println('  You can also pass -h or --help after each vpm command from the above, to see more details about it.')
}
