use iced::{
    widget::{column, image, text, button, row},
     Sandbox, Settings, Color, Alignment, Length,
};//use crates of iced framework
use rand::prelude::*; //use crate of rand 
use std::fs; //use file system crate
//use std::env::current_dir;
//use std::path::PathBuf;
//use std::path::Path;
use pathtrim::TrimmablePath;


//function giving me random number from 1 to right_border
fn rand_range_num(right_border:i32)-> String{
	let mut rng = rand::thread_rng();
	let mut nums: Vec<i32> = (1..right_border).collect();
	nums.shuffle(&mut rng);
	nums[0].to_string()
}
//function giving me the random number from right_border to 288
fn rand_range_num2(right_border:i32)-> String{
	let mut rng = rand::thread_rng();
	let mut nums: Vec<i32> = (right_border..288).collect();
	nums.shuffle(&mut rng);
	nums[0].to_string()
}
//same like ^^^
fn rand_range_num3(right_border:i32)-> String{
	let mut rng = rand::thread_rng();
	let mut nums: Vec<i32> = (right_border..23).collect();
	nums.shuffle(&mut rng);
	nums[0].to_string()
}
//same like ^^^
fn rand_range_num4(right_border:i32)-> String{
	let mut rng = rand::thread_rng();
	let mut nums: Vec<i32> = (right_border..27).collect();
	nums.shuffle(&mut rng);
	nums[0].to_string()
}

//function returning the current directory of exe/elf
fn cur_dir1()->String{
	//let path = current_dir().unwrap();
	//path.display().to_string().clone()
	let path = process_path::get_executable_path();
	//let srcdir = PathBuf::from("./");
	//fs::canonicalize(&srcdir).expect("Error returning the path from fs:: module... ").into_os_string().into_string().unwrap()
	match path {
		None => String::from("The process path could not be determined... "),
		Some(path) => {
			let len = path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").chars().count();
			let outa_path_exe=path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").drain(0..len).collect::<String>();
			//let to_replace = path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap();
			//let target_str = outa_path_exe.replace(to_replace.as_str(),"");
			let to_replace=String::from("/");
			let mut del_farther:usize=0;
			if let Some(last_index) = outa_path_exe.as_str().rfind(&to_replace.as_str()) {
				del_farther = last_index;
			}
			outa_path_exe.as_str()[0..del_farther].to_string()+"/"
			//path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap()
			//target_str.to_string()			
		}
	}
}

//calling main function in rust language
fn main() -> iced::Result {
    MyApp::run(Settings::default())
}
//enum with app signals definitions:
#[derive(Debug, Clone)]
enum MyAppMessage {
    GoZakon,
    GoZnacka,
    GoKrizovatka,
    GiveAnswer,
    GoLaw,
    GoSign,
    GoIntersection
}
//state of the application based on iced framework documentation:
#[derive(Default)]
struct MyApp{
	pic_value:String,
	question_value:String,
	answer_value:String,
	q_num:String,
	t_num:String,
	q_type:String,
	}
//implementation for myapp struct:
impl Sandbox for MyApp {
    type Message = MyAppMessage;//type alias
    //app window constructor:
    fn new() -> Self {
        Self{
			pic_value: String::from(""),
			question_value: String::from("Sem načítam otázku po kliknutí na príslušné tlačítko...\n Here I load the question after adequate button click..."),
			answer_value: String::from("Sem načítam odpoveď po kliknutí na príslušné tlačítko...\n Here I load the answer after adequate button click..."),
			q_num: String::from("1"), //global random number of the SLOVAK question
			q_type: String::from("za"), //whether zakony za or znacky zn
			t_num:String::from("1"), //just the first English test as we know t1o1.txt means test1 otazka1
		}
    }
    //title of app window:
    fn title(&self) -> String {
        String::from("Autoškola3 EN+SK: 2000 questions | Mgr. Janko Hruboš | janko.hrubos@gmail.com")
    }
    //on the state update and signals receiving do these actions:
    fn update(&mut self, message: Self::Message) {
		 match message {
            MyAppMessage::GoZakon => {
				
                self.pic_value = cur_dir1()+"/resources/empty.jpg";
                //println!("{}",cur_dir1());
                self.q_num=rand_range_num(525);                 
                let mut s2:String=cur_dir1()+"/resources/sk/otza/za_";
                let s3:String=".txt".to_owned();
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect("ERROR: Cant read the file, sorry...");
				self.q_type=String::from("za");
				self.answer_value=String::from("");
								
                //^^^ self explanatory
            }
            MyAppMessage::GoZnacka => {                
                self.q_num=rand_range_num(144);                                 
                let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();                
                self.pic_value = s4;
                let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
                let s3:String=".txt".to_owned();
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect("ERROR: Cant read the file, sorry...");
				self.q_type=String::from("zn");
				self.answer_value=String::from("");
                              
            }
            
            MyAppMessage::GoKrizovatka => {
                self.q_num=rand_range_num2(144);                                 
                let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();                
                self.pic_value = s4;
                let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
                let s3:String=".txt".to_owned();
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect("ERROR: Cant read the file, sorry...");
				self.q_type=String::from("kri");
				self.answer_value=String::from("");
            }
            MyAppMessage::GoLaw => {
				self.q_num=rand_range_num(15);//generate random question from 1 to 27
				self.t_num=rand_range_num(35);//generate random test from 1 to 35
                //let s4:String=("resources/en/znackyobr/z".to_owned()+&self.q_num+".jpg").to_string().clone();                
                self.pic_value = String::from(cur_dir1()+"/resources/empty.jpg");
                let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
                let s3:String=".txt".to_owned();
                let s5:String="o".to_owned();
                s2.push_str(&self.t_num);
                s2.push_str(&s5);
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect("ERROR: Cant read the file, sorry...");
				self.q_type=String::from("law");
				self.answer_value=String::from("");
            }
            MyAppMessage::GoSign => {
                self.q_num=rand_range_num3(16);//generate random question from 16 to 23
				self.t_num=rand_range_num(35);//generate random test from 1 to 35
                let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();                
                //println!("{}",s4); //debug printout
                self.pic_value = s4;
                let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
                let s3:String=".txt".to_owned();
                let s5:String="o".to_owned();
                s2.push_str(&self.t_num);
                s2.push_str(&s5);
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect("ERROR: Cant read the file, sorry...");
				self.q_type=String::from("sig");
				self.answer_value=String::from("");
                
                
            }
            MyAppMessage::GoIntersection => {
                self.q_num=rand_range_num4(24);//generate random question from 24 to 27
				self.t_num=rand_range_num(35);//generate random test from 1 to 35
                let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();                
                //println!("{}",s4); //debug printout
                self.pic_value = s4;
                let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
                let s3:String=".txt".to_owned();
                let s5:String="o".to_owned();
                s2.push_str(&self.t_num);
                s2.push_str(&s5);
                s2.push_str(&self.q_num);
                s2.push_str(&s3); 
                self.question_value = fs::read_to_string(s2)
					.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1()));
				self.q_type=String::from("int");//question type is intersection
				self.answer_value=String::from("");//answer is not visible yet, coz intersection button pressed not answer button
                //^^^ self explanatory what to do on these signals receiving
                
            }
            MyAppMessage::GiveAnswer => { //on button answer click:
				let qnum = self.q_num.clone();
				let tnum = self.t_num.clone();
				let qtype = self.q_type.clone();
				if qtype == "za" { //if this is Slovak zakon you know qnum is from 1 to 525
					let mut s2:String=cur_dir1()+"/resources/sk/otza/zao_";
					let s3:String=".txt".to_owned();
					s2.push_str(&qnum);
					s2.push_str(&s3);
					self.answer_value=String::from("Odpoveď na otázku zákony ");
					self.answer_value.push_str(&qnum); 
					let s4:String=" je: ".to_owned();
					self.answer_value.push_str(&s4);
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect("ERROR: Cant read the file, sorry..."));
					
				}
				
				if qtype == "zn" { //if this is Slovak znacka you know qnum is from 1 to 144
					let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
					let s3:String=".txt".to_owned();
					s2.push_str(&qnum);
					s2.push_str(&s3);
					self.answer_value=String::from("Odpoveď na otázku značky ");
					self.answer_value.push_str(&qnum); 
					let s4:String=" je: ".to_owned();
					self.answer_value.push_str(&s4);
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect("ERROR: Cant read the file, sorry..."));
					
				}
				
				if qtype == "kri" { //if this is Slovak znacka you know qnum is from (1 to 144)+144
					let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
					let s3:String=".txt".to_owned();
					s2.push_str(&qnum);
					s2.push_str(&s3);
					self.answer_value=String::from("Odpoveď na otázku križovatky ");
					self.answer_value.push_str(&qnum); 
					let s4:String=" je: ".to_owned();
					self.answer_value.push_str(&s4);
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect("ERROR: Cant read the file, sorry..."));
					
				}
				
				if qtype == "law" { 
					let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
					//let s3:String=".txt".to_owned();
					let s5:String="od".to_owned();
					s2.push_str(&tnum);
					s2.push_str(&s5);
					s2.push_str(&qnum);
					//s2.push_str(&s3);
					self.answer_value=String::from("Answer to the question from laws ");
					self.answer_value.push_str(&qnum); 
					let s4:String=" is: ".to_owned();
					self.answer_value.push_str(&s4);
					//println!("{}",s2);					
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect("ERROR: Cant read the file, sorry..."));
					
				}
				
				if qtype == "sig" { 
					let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
					//let s3:String=".txt".to_owned();
					let s5:String="od".to_owned();
					s2.push_str(&tnum);
					s2.push_str(&s5);
					s2.push_str(&qnum);
					//s2.push_str(&s3);
					self.answer_value=String::from("Answer to the question from signs ");
					self.answer_value.push_str(&qnum); 
					self.answer_value.push_str(" / test ");
					self.answer_value.push_str(&tnum); 
					let s4:String=" is: ".to_owned();
					self.answer_value.push_str(&s4);
					//println!("{}",s2);					
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect("ERROR: Cant read the file, sorry..."));
					
				}
				
				if qtype == "int" { 
					let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
					//let s3:String=".txt".to_owned();
					let s5:String="od".to_owned();
					s2.push_str(&tnum);
					s2.push_str(&s5);
					s2.push_str(&qnum);
					//s2.push_str(&s3);
					self.answer_value=String::from("Answer to the question from intersections ");
					self.answer_value.push_str(&qnum); 
					self.answer_value.push_str(" / test ");
					self.answer_value.push_str(&tnum); 
					let s4:String=" is: ".to_owned();
					self.answer_value.push_str(&s4);
					//println!("{}",s2);					
					self.answer_value.push_str(&fs::read_to_string(s2)
						.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1())));
					
				}
				
                
            }
            
        }
		
		}
	//basic view definitions with slots of signals:
    fn view(&self) -> iced::Element<'_, Self::Message> {
        let padding1:u16=10;//padding of 10px
        column![ 	  
            image(self.pic_value.clone()).width(600),
            row![button("Náhodný zákon").on_press(MyAppMessage::GoZakon).padding(padding1),
            button("Náhodná značka").on_press(MyAppMessage::GoZnacka).padding(padding1),
            button("Náhodná križovatka").on_press(MyAppMessage::GoKrizovatka).padding(padding1)],
            row![button("Answer/Opoveď").on_press(MyAppMessage::GiveAnswer).padding(padding1)],
            row![button("Random law").on_press(MyAppMessage::GoLaw).padding(padding1),
            button("Random sign").on_press(MyAppMessage::GoSign).padding(padding1),
            button("Random intersection").on_press(MyAppMessage::GoIntersection).padding(padding1),],
            text(self.question_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
            text(self.answer_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
        ].width(Length::Fill).align_items(Alignment::Center).padding(20)
        .into()
    }
}
