use piston_window::*;
use find_folder;

trait State{
    fn update(&mut self,args:&UpdateArgs);
    fn input(&mut self,button:Button)->Option<StateCommand>;
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:Glyphs);
}
enum StateCommand{
    Push(Box<dyn State>),
    Pop,
    None,
}
struct Mainpage{
    circle_x:f64,
    direction:f64,
    fps_timer:f64,
    fps_count:u32,
    fps:u32,
}
impl Mainpage {
    fn new()->Self{
        Self { circle_x: 320.0
            , direction: 100.0
            , fps_timer: 0.0
            , fps_count: 0
            , fps: 0 }
    }
}
struct StateStack{
    stack:Vec<Box<dyn State>>
}

impl StateStack {
    fn new(initial_state:Box<dyn State>)->Self{
        Self { stack: vec![initial_state] }
    }
    fn push(&mut self,state:Box<dyn State>){
        self.stack.push(state);
    }
    fn pop(&mut self){
        self.stack.is_empty(){
            return;
        }
        self.stack.pop();
        if self.stack.is_empty(){
            println!("堆疊結束");
        }
    }

    fn is_empty(&self)->bool{
        self.stack.is_empty()
    }
    fn update(&mut self,args:&UpdateArgs){
        if let Some(top)=self.stack.last_mut(){
            top.update(args);
        }
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs){
        for state in &mut self.stack{
            state.render(c, g, glyphs);
        }
    }
    fn input(&mut self,button:Button)->Option<StateCommand>{
        if let Some(top)=self.stack.last_mut(){
            if let Some(cmd)=top.input(button){
                match cmd  {
                    StateCommand::Push(state)=>self.push(state),
                    StateCommand::Pop=>self.pop(),
                    StateCommand::None=>{}
                }
            }
        }

    }
}

struct ModalWindow{
    count:usize
}
impl ModalWindow{
    fn new()->Self{
        Self { count: 0 }
    }
}
impl State for ModalWindow {
    fn input(&mut self,button:Button)->Option<StateCommand> {
        if let Button::Keyboard(Key)=button{
            match Key {
                Key::Escape=>return Some(StateCommand::Pop),
                Key::Space=>{
                        self.count +=1;
                        println!("{}",self.count);
                        return Some(StateCommand::None);
                }
                _=>{}
            }
        }
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:Glyphs) {
        graphics::rectangle([0.0,0.0,0.0,0.5], [0.0,0.0,640.0,480.0], c.transform, g);
        let rect =[120.0,140.0,400.0,240.0];
        graphics::rectangle([1.0;4],rect,c.transform,g);
        let text_obj=graphics::text::Text::new_color([0.0,0.0,0.0,1.0], 32);
        text_obj.draw("這是彈出視窗", glyphs, &graphics::DrawState::default(), c.transform.trans(180.0,200.0), g,).unwrap();
        text_obj.draw("按esc,關閉", glyphs, &graphics::DrawState::default(), c.transform.trans(120.0, 240.0), g).unwrap();
        let conter_str=format!("按下空白鍵{}",self.count);
        text_obj.draw(&conter_str, glyphs, graphics::DrawState::default(), c.transform.trans(180.0, 280.0), g).unwrap();
    }
}

impl State for Mainpage {
    fn update(&mut self,args:&UpdateArgs) {
        self.circle_x += self.direction *args.dt;
        if self.circle_x > 660.0{
            self.circle_x=660.0;
            self.direction= -self.direction;
        }else if self.circle_x <40.0 {
            self.circle_x=40.0;
            self.direction=-self.direction;
        };
        self.fps_timer +=args.dt;
        self.fps_count +=1;
        if self.fps_timer >= 1.0 {
            self.fps=self.fps_count;
            self.fps_timer -=1.0;
            self.fps_count =0;
        }
    
    }
    fn input(&mut self,button:Button)->Option<StateCommand> {
        if let Some(Button::Keyboard(Key))=button{
            if Key==Key::M{return  Some(StateCommand::Push(Box::new(ModalWindow::new())));}
        }
        None
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:Glyphs) {
        clear([0.8,0.8,1.0,1.0], g);

        draw_text_centered("text_str", c, g, glyphs, 240.0);

        graphics::ellipse([1.0,0.0,0.0,1.0],[self.circle_x-20.0,300.0-20.0,40.0,40.0],c.transform,g,);

        let fps_text=format!("FPS:{}",self.fps);
        let text_obj=graphics::text::Text::new_color([0,0,0.0,0.0,1.0], 24);
        text_obj.draw(&fps_text, glyphs, &graphics::DrawState::default(), c.transform.trans(10.0,460.0), g).unwrap();
    }
}

fn draw_text_centered(
    text_str:&str,
    c:Context,g:&mut G2d,glyphs:&mut Glyphs,y:f64
){
    use graphics::Transformed;
    let text_width=text_str.len() as f64 *24.0/2.0;
    let x=320.0-text_width;
    let transform=c.transform.trans(x, y);
    let text_obj=graphics::text::Text::new_color([1.0;4], 32);
    text_obj.draw(
        text_str, glyphs, &graphics::DrawState::default(), transform, g).unwrap();
}

fn main(){
    let mut windows:PistonWindow=WindowSettings::new("狀態", [640.0,480.0]).exit_on_esc(true).build().unwrap();
    let assets=find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").expect("找不到assets資料夾");
    let font_path=assets.join("mingliu.ttc");
    let mut glyphs=windows.load_font(font_path).expect("無法載入自型");
    let mut state_stack=StateStack::new(Box::new(Mainpage::new()));
    while let Some(event) = windows.next() {
        if let Some(button)=event.press_args(){
            state_stack.input(button);
        }
        if let Some(args)=event.update_args(){
            state_stack.update(&args);
        }
        windows.draw_2d(&event, |c,g,device|{
            state_stack.render(c, g, &mut glyphs);

            glyphs.factory.encoder.flush(device);
        });

        if state_stack.is_empty(){
            break;
        }
    }
}
請找修正