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,
	// which provides the path to V inside os.getenv('VEXE')
	args := os.args // args are: vpm SUBCOMMAND module names
	if args.len < 2 {
		vpm_help([])
		exit(5)
	}
	vpm_command := args[1]
	module_names := args[2..]
	// 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.is_dir(home_vmodules) {
		println('Creating $home_vmodules/ ...')
		os.mkdir(home_vmodules) or {
			panic(err)
		}
	}
}

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('  a) v install module [module] [module] [...]')
	println('  b) v update [module] [...]')
	println('  c) v remove [module] [...]')
	println('  d) v search keyword1 [keyword2] [...]')
	println('')
	println('  You can also pass -h or --help after each vpm command from the above, to see more details about it.')
}