use piston_window::*;
use find_folder;


trait State {
    fn update(&mut self,args:&UpdateArgs);
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs);
    fn input(&mut self,button:Button)->Option<StateCommand>;
    fn mouse_input(&mut self,cursor:[f64;2],button:MouseButton)->Option<StateCommand>{None}
    fn name(&self)->&'static str;
    fn page_id(&self)->Option<PagId>;
}

enum StateCommand{
    Push(Box<dyn State>),
    Repalce(Box<dyn State>),
    Pop,a
    SwitchPage(PagId),
    None,
}
#[derive(Debug,PartialEq, Eq,Clone, Copy)]
enum PagId{
    Main=1,
    Second=2,
    Third=3,
}
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 render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs){
        for state in &mut self.stack{
            state.render(c, g, glyphs);
        }
    }
    fn pop(&mut self){
        if 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 input(&mut self,button:Button){
        if let Some(top)=self.stack.last_mut(){
            if let Some(cmd)=top.input(button){
                self.hadle_command(cmd);
            }
        }
    }
    fn mouse_input(&mut self,cursor:[f64;2],button:MouseButton){
        if let Some(top)=self.stack.last_mut(){
            if let Some(cmd)=top.mouse_input(cursor, button){
                self.hadle_command(cmd);
            }
        }
    }
    fn hadle_command(&mut self,cmd:StateCommand){
        match cmd {
            StateCommand::Push(state)=>{
                println!("Push state:{}",state.name());
                self.push(state);
            }
            StateCommand::Pop=>{
                println!("Pop state");
                self.pop();
            }
            StateCommand::Repalce(state)=>{
                println!("Replace witch:{}",state.name());
                self.pop();
                self.push(state);
            }
            StateCommand::SwitchPage(page)=>{
                println!("Switch to page{:?}",page);
                self.stack.clear();

                let new_state:Box<dyn State>=match page {
                    PagId::Main=>Box::new(MainPage::new()),
                    PagId::Second=>Box::new(SecondPage::new()),
                    PagId::Third=>Box::new(ThirdPage::new()),
                    
                };
                if self.stack.is_empty(){
                    self.stack.push(new_state);
                }else {
                    self.stack.pop();
                    self.stack.push(new_state);
                }
            }
        StateCommand::None=>{}
        }
    }
}
fn handle_page_switch(cursor:[f64;2],current_page:PagId)->Option<StateCommand>{
    let x=cursor[0];
    let y=cursor[1];
    
    if x>=5.0 && x<=50.0 {
        for (i,page) in [PagId::Main,PagId::Second,PagId::Third].iter().enumerate(){
            let y_start=50.0+i as f64 *30.0;
        if y>=y_start && y<=y_start+28.0 && *page != current_page{
                return Some(StateCommand::SwitchPage(*page));
        }
        }
    }
    None

}

//=============================MainPage=======================
struct MainPage{
    circle_x:f64,
    direction:f64,
    fps_timer:f64,
    fps_count:u32,
    fps:u32,
}
impl MainPage{
    fn new()->Self{
        Self { circle_x: 300.0,
             direction: 100.0,
              fps_timer: 0.0,
               fps_count: 0,
                fps: 0 }

    }
}
impl State for MainPage{
    fn update(&mut self,args:&UpdateArgs) {
        self.circle_x+=self.direction*args.dt;
        if self.circle_x>=600.0{
            self.circle_x=600.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{
            match key {
                Key::M=>Some(StateCommand::Push(Box::new(ModalWindow::new()))),
                Key::Right=>Some(StateCommand::SwitchPage(PagId::Second)),
                Key::Left=>Some(StateCommand::SwitchPage(PagId::Third)),
                _=>None,
            }
        }else {
            None
        }
    }
    fn mouse_input(&mut self,cursor:[f64;2],button:MouseButton)->Option<StateCommand> {
        if button==MouseButton::Left{
            if let Some(page)=self.page_id(){
                return handle_page_switch(cursor, page);
            }
        }
        None
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs) {
        clear([0.8,0.8,1.0,1.0], g);
        draw_page_centered("主頁面(按M)彈出視窗", c, g, glyphs,240.0);

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

        let text_fps=format!("FPS:{}",self.fps);
        graphics::text::Text::new_color([0.0,0.0,0.0,1.0], 24).draw(
            &text_fps, glyphs, &graphics::DrawState::default(), c.transform.trans(10.0, 460.0), g).unwrap();
            draw_page_numbers(c, g, glyphs, self.page_id().unwrap());
    }
    fn name(&self)->&'static str {
        "MainPage"
    }
    fn page_id(&self)->Option<PagId> {
        Some(PagId::Main)
    }
}
//=============================SecondPage=======================
struct SecondPage{
    circle_y:f64,
    directio:f64,
}
impl SecondPage{
    fn new()->Self{
        Self { circle_y: 240.0,
             directio: 120.0 }
    }
}
impl State for SecondPage {
    fn update(&mut self,args:&UpdateArgs) {
        self.circle_y+=self.directio*args.dt;
        if self.circle_y >440.0{
            self.circle_y=440.0;
            self.directio=-self.directio;
        }else if self.circle_y <40.0{
            self.circle_y=40.0;
            self.directio=-self.directio;
        }
    }
    fn input(&mut self,button:Button)->Option<StateCommand> {
        if let Button::Keyboard(key)=button{
            match key {
                Key::Escape=>Some(StateCommand::Pop),
                Key::Right=>Some(StateCommand::SwitchPage(PagId::Third)),
                Key::Left=>Some(StateCommand::SwitchPage(PagId::Main)),
                _=>None,
            }
        }else {
            None
        }
    }
    fn mouse_input(&mut self,cursor:[f64;2],button:MouseButton)->Option<StateCommand> {
        if button==MouseButton::Left{
            if let Some(page)=self.page_id(){
                return handle_page_switch(cursor,page);
            }
        }
    None
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs) {
        clear([0.9,1.0,0.9,1.0], g);
        draw_page_centered("第二頁(綠色的球往上)", c, g, glyphs, 240.0);
        graphics::ellipse([0.0,0.8,0.0,1.0], [320.0-20.0,self.circle_y-20.0,40.0,40.0],
             c.transform, g);

             draw_page_numbers(c, g, glyphs, self.page_id().unwrap());
        
    }
    fn name(&self)->&'static str {
        "SecondPage"
    }
    fn page_id(&self)->Option<PagId> {
        Some(PagId::Second)
    }
}
//=============================ThirdPage=======================
struct ThirdPage{
    circle_y:f64,
    direction:f64,
}
impl ThirdPage{
    fn new()->Self{
        Self { circle_y: 480.0,
              direction:-100.0
        }
    }
}
impl State for ThirdPage {
    fn update(&mut self,args:&UpdateArgs) {
        self.circle_y+=self.direction*args.dt;
        if self.circle_y <40.0 {
            self.circle_y=40.0;
            self.direction=-self.direction;
        }else if self.circle_y>480.0{
            self.circle_y=480.0;
            self.direction=-self.direction;
        };

    }
    fn input(&mut self,button:Button)->Option<StateCommand> {
        if let Button::Keyboard(key)=button{
         match key {
             Key::Escape=>Some(StateCommand::Pop),
             Key::Right=>Some(StateCommand::SwitchPage(PagId::Main)),
             Key::Left=>Some(StateCommand::SwitchPage(PagId::Second)),
             _=>None,
         }   
        }else {
            None
      }
   }
    fn mouse_input(&mut self,cursor:[f64;2],button:MouseButton)->Option<StateCommand> {
        if button==MouseButton::Left{
            if let Some(page)=self.page_id(){
                return handle_page_switch(cursor, page);
            }
        }
      None
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs) {
        clear([0.95,0.9,1.0,1.0], g);
        draw_page_centered("紫色球往下", c, g, glyphs, 240.0);
        graphics::ellipse([0.6,0.0,0.8,1.0],[320.0-20.0,self.circle_y-20.0,40.0,40.0],
            c.transform, g);
            draw_page_numbers(c, g, glyphs, self.page_id().unwrap());
    }
fn name(&self)->&'static str {
    "ThirdPage"
}
fn page_id(&self)->Option<PagId> {
    Some(PagId::Third)
}

}
//=============================ModalWindow=======================
struct ModalWindow{
    counter:usize
}
impl ModalWindow{
    fn new()->Self{
        Self { counter: 0 }
    }
}
impl State for ModalWindow {
    fn update(&mut self,args:&UpdateArgs) {}
    fn input(&mut self,button:Button)->Option<StateCommand> {
        if let Button::Keyboard(key)=button{
            match key {
                Key::Escape=>Some(StateCommand::Pop),
                Key::Space=>{
                    self.counter+=1;
                    println!("計數器增加到{}",self.counter);
                    Some(StateCommand::None)
                }
            _=>None,
            }
        }else {
            None
        }
    }
    fn render(&mut self,c:Context,g:&mut G2d,glyphs:&mut Glyphs) {
        graphics::rectangle([0.0,0.0,0.0,0.5], [0.0,0.0,640.0,480.0],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 counter_str=format!("按空白建下次數{}",self.counter);
        text_obj.draw(&counter_str, glyphs, &graphics::DrawState::default(), c.transform.trans(180.0, 280.0), g).unwrap();
    }
    fn name(&self)->&'static str {
        "ModalWindow"
    }
    
}
//===================工具函數==================
fn draw_page_centered(
    text_str:&str,
    c:Context,
    g:&mut G2d,
    glyphs:&mut Glyphs,
    y:f64,
){
    use graphics::Transformed;
    let font_size=48;
    let width=glyphs.width(font_size, text_str).unwrap_or(0.0);
    let x=320.0-width/2.0;
    let transform=c.transform.trans(x, y);
    let text_obj=graphics::text::Text::new_color([0.0,0.0,0.0,1.0], font_size);
    text_obj.draw(text_str, glyphs,&graphics::DrawState::default(), transform, g).unwrap();

}

fn draw_page_numbers(c:Context,g:&mut G2d,glyphs:&mut Glyphs,current:PagId){
    let pages=[
        (PagId::Main,"主頁"),
        (PagId::Second,"第二頁"),
        (PagId::Third,"第三頁"),
    ];
    for (i,(id,name)) in pages.iter().enumerate(){
        let y=5.0 + i as f64 *30.0;
        let color =if  *id==current{
            [1.0;4]
        } else {
            [0.0,0.0,0.0,1.0]
        };

        let text_obj=graphics::text::Text::new_color(color, 24);
        text_obj.draw(name, glyphs, &graphics::DrawState::default(), c.transform.trans(5.0, y+20.0), g).unwrap();
    }
}

fn main(){
    let mut window22:PistonWindow=WindowSettings::new("title", [640,480]).exit_on_esc(true).build().unwrap();
    let assets=find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").expect("找不到資料夾");
    let font_path=assets.join("mingliu.ttc");
    let mut glyphs=window22.load_font(assets).expect("找不到字形");
    let mut state_stack=StateStack::new(Box::new(MainPage::new()));
    let mut cursor_pos:Option<[f64;2]>=None;
    while let Some(event) = window22.next() {
        if let Some(pos)=event.mouse_cursor_args(){
            cursor_pos=Some(pos);
        }
        if let Some(button)=event.press_args(){
            state_stack.input(button);
        }
        if let Some(button_args)=event.button_args(){
            if let Button::Mouse(mouse_button)=button_args.button{
                if let Some(cursor)=cursor_pos{
                    state_stack.mouse_input(cursor, mouse_button);
                }
            }
        }
        if let Some(args) = event.update_args() {
            state_stack.update(&args);
        }
        window22.draw_2d(&event, |c,g,device|{

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

       

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