/*
 * Copyright (C) 2022 Ortega Froysa, Nicolás <nicolas@ortegas.org>
 * Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

use structopt::StructOpt;
use structopt::clap::AppSettings;
use std::env;
use std::path::PathBuf;
use std::fs;

mod habit;
mod habitmgr;
use habitmgr::HabitMgr;

#[derive(StructOpt)]
#[structopt(
	setting = AppSettings::InferSubcommands,
	about = "A CLI tool to help form good habits and lose bad ones.")]
struct Opts
{
	#[structopt(subcommand)]
	cmd:Option<Command>,
}

#[derive(StructOpt)]
enum Command
{
	#[structopt(alias = "a")]
	Add
	{
		#[structopt(help = "name of the new habit")]
		name:String,
		#[structopt(long, short, default_value = "mon,tue,wed,thu,fri,sat,sun")]
		days:String,
		#[structopt(long)]
		bad:bool,
		#[structopt(short, long, default_value = "5")]
		weight:u8,
	},
	Commit { },
	#[structopt(alias = "del")]
	Delete {
		#[structopt(help = "ID of the habit to delete")]
		id:usize,
	},
	#[structopt(alias = "i")]
	Info {
		id:usize,
	},
	#[structopt(alias = "ls")]
	List
	{
		#[structopt(short, long, help = "list all active habits")]
		all:bool,
		#[structopt(short, long, help = "show UUIDs")]
		verbose:bool,
	},
	#[structopt(alias = "mod")]
	Modify {
		#[structopt(help = "ID of the habit to modify")]
		id:usize,
		#[structopt(short, long)]
		name:Option<String>,
		#[structopt(short, long)]
		weight:Option<u8>,
		#[structopt(long, short)]
		days:Option<String>,
		#[structopt(long)]
		toggle_bad:bool,
	},
	#[structopt(alias = "stats")]
	Statistics { },
}

fn main()
{
	let opts = Opts::from_args();

	let data_dir =
		PathBuf::from(
			env::var("XDG_DATA_HOME")
			.unwrap_or_else(|e| { panic!("Error: {}", e); }))
		.join("htracker");

	if data_dir.exists() && data_dir.is_file()
	{
		panic!("Error: file exists at '{}', please (re)move it.",
			data_dir.display());
	}
	else if !data_dir.exists()
	{
		println!("First run: files will be stored in {}", data_dir.display());
		fs::create_dir_all(&data_dir)
			.unwrap_or_else(|e| { panic!("Filesystem error: {}", e); });
	}

	let mut hmgr = HabitMgr::new(&data_dir);

	match opts.cmd
	{
		None => hmgr.list(false, false),
		Some(c) =>
			match c
			{
				Command::Add { name, days, bad, weight } =>
					hmgr.add(name, bad, weight, days),
				Command::Delete { id } =>
					hmgr.delete(id),
				Command::Info { id } =>
					hmgr.habit_info(id),
				Command::List { all, verbose } =>
					hmgr.list(all, verbose),
				Command::Modify { id, name, weight, days, toggle_bad } =>
					hmgr.modify(id, name, toggle_bad, weight, days),
				_ => todo!(),
			},
	}
}