use std::vec;

fn main() {
    let args: Vec<String> = std::env::args().skip(1).collect();
    if args.len() == 0 {
        println!("Rinana is sleepy eepy");
        return;
    };
    let mut cloud = CloudBuilder::new();
    cloud.insert_text(args);
    cloud.make_text_cloud_vec();
    let res = cloud.asamble();
    if let Ok(res) = res {
        println!("{}",res);
        println!("{RINANA}");
    } else {
        println!("Rinana couldn't pronounce it");
    }


}

const MAX_WIDTH: usize = 40;

const RINANA:&str = r#"    \
     \
     /^-----^\
     V  o o  V
      |  Y  |
       \ Q /
       / - \
       |    \
       |     \     )
       || (___\====
"#;

#[derive(Debug, Clone)]
struct CloudBuilder {
    text_lines:Vec<String>,
    cloud_lines:Vec<String>,
    max_width:usize,
}

impl CloudBuilder{
    pub fn new() -> CloudBuilder {
        CloudBuilder { text_lines: vec![], cloud_lines: vec![], max_width: 0}
    }

    fn asamble(self) -> Result<String,String> {
        let mut cloud_lines_iter = self.cloud_lines.into_iter();
        let mut res = String::new();
        if cloud_lines_iter.len() != self.text_lines.len() * 2 + 2 {
            return Err("Asamble error".to_string());
        }
        res.push_str(&cloud_lines_iter.next().unwrap());
        res.push_str("\n");
        for line in self.text_lines {
            res.push_str(&cloud_lines_iter.next().unwrap());
            res.push_str(&line);
            res.push_str(&" ".repeat(self.max_width - line.len()));
            res.push_str(&cloud_lines_iter.next().unwrap());
        res.push_str("\n");
        }
        res.push_str(&cloud_lines_iter.next().unwrap());
        return Ok(res)
    }

    fn make_text_cloud_vec(&mut self){
        let top = "_";
        let bottom = "-";
        self.cloud_lines.push(" ".to_string() + &top.repeat(self.max_width) + " ");

        if self.text_lines.len() == 1  {
            self.cloud_lines.append(&mut vec!["<".to_string(), ">".to_string()]);
        } else {
            self.cloud_lines.append(&mut vec!["/".to_string(), "\\".to_string()]);
            self.cloud_lines.append(&mut "|".repeat(self.text_lines.len() * 2 - 4).chars().map(|x|{x.to_string()}).collect());
            self.cloud_lines.append(&mut vec!["\\".to_string(), "/".to_string()]);
        };
        self.cloud_lines.push(" ".to_string() + &bottom.repeat(self.max_width) + " ");
    }

    fn insert_text(&mut self, words:Vec<String>){
        // let mut inner_line: Vec<String> = vec![];
        // let mut char_count: usize = 0;
        // for word in words {
        //     let char_count = self.text_lines.last().unwrap_or(&"".to_string()).len();
        //     if char_count != 0 && char_count + word.len() > MAX_WIDTH {
        //         self.push_line_vec(inner_line.split_off(0));
        //         char_count = 0;
        //     }
        //     char_count += word.len() + 1;
        //     inner_line.push(word);
        // }
        // self.push_line_vec(inner_line.split_off(0));
        for word in words {
            self.push_word(word);
        }
    }

    fn last_line_len(&self) -> usize {
        return self.text_lines.last().unwrap_or(&"".to_string()).len();
    }

    fn push_word(&mut self, mut word:String) {
        if self.last_line_len() + 1 + word.len() > MAX_WIDTH {
            if word.len() < MAX_WIDTH {
                self.add_to_new_line(word);// pushes word to next line because i want it to do it
            } else {
                let mut space_left = if self.last_line_len() < MAX_WIDTH {MAX_WIDTH - self.last_line_len() - 1} else {0};
                if space_left == 0 {
                    self.add_to_new_line(String::new());
                    space_left = MAX_WIDTH;
                }
                let remainder = word.split_off(space_left);
                
                self.add_to_last_line(word);
                self.push_word(remainder);
            }
        } else {
            self.add_to_last_line(word);
        } 
    }
    fn add_to_new_line(&mut self, word:String) {
        self.text_lines.push(word);
    }

    fn add_to_last_line(&mut self, word:String) {
        if let Some(line) = self.text_lines.last_mut() {
            if line.len() > 0 {
                line.push_str(" ");
            }
            line.push_str(&word);//push word if there is an unfinished line
        } else {
            self.add_to_new_line(word);//push word if there are no lines
        }
        
        if self.last_line_len() > self.max_width {
            self.max_width = self.last_line_len();
        }
    }
}
