use piston_window::*;
use find_folder;

trait State {
    fn input(&mut self,button:Button)->Option<StateCommand>;
    fn update(&mut self,_args:&UpdateArgs);
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs);
}

enum StateCommand{
    Push(Box<dyn State>),
    Pop,
    None,
}

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){
        if self.stack.is_empty(){
            return;
        }
        self.stack.pop();
        if self.stack.is_empty(){
            println!("堆疊結束")
        }
    }
    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){
        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=>{}
                    }
            }
        }
    }  
    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);
        }
    }

}

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 ModalWindow{
    count:usize
}
impl ModalWindow{
    fn new()->Self{
        Self { count: 0 }
    }
}
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 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:&mut Glyphs) {
        clear([0.8,0.8,0.8,1.0], g);
        draw_text_centered(
            "主頁面", c, g, glyphs, 240.0);
            graphics::ellipse(
                [1.0;4], 
                [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([1.0;4], 24);
        text_obj.draw(
            &fps_text,
             glyphs,
              &graphics::DrawState::default(),
               c.transform.trans(10.0, 460.0),
                g).unwrap();


    }
}

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);
                    }
                    _=>{}
                }
            }
        None
        }
        fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs) {
            graphics::rectangle(
                [1.0;4], 
                [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([1.0;4], 32);
            text_obj.draw("這是彈出視窗",glyphs, &graphics::DrawState::default(), c.transform.trans(180.0, 200.0), g,).unwrap();

            text_obj.draw(
                "按ECS關閉",
                 glyphs,
                  &graphics::DrawState::default(),
                   c.transform.trans(120.0, 240.0),
                    g).unwrap();
            let counter_str=format!("空白鍵按下:{}",self.count);
            text_obj.draw(
                &counter_str,
                 glyphs,
                  &graphics::DrawState::default(),
                   c.transform.trans(180.0, 280.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 window:PistonWindow=WindowSettings::new("gdgd", [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=window.load_font(font_path).expect("無法載入自型");
    let mut state_stack=StateStack::new(Box::new(MainPage::new()));

    while let Some(event) = window.next() {
        if let Some(button) = event.press_args() {
            state_stack.input(button);
        }
          if let Some(args) = event.update_args() {
            state_stack.update(&args);
        }
        window.draw_2d(&event, |c, g, device| {
            state_stack.render(c, g, &mut glyphs);
         
            glyphs.factory.encoder.flush(device);
        });

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