use crate::editor::RUSTERIX;
use crate::prelude::*;

pub struct ClearTile {
    id: TheId,
    nodeui: TheNodeUI,
}

impl Action for ClearTile {
    fn new() -> Self
    where
        Self: Sized,
    {
        let mut nodeui: TheNodeUI = TheNodeUI::default();
        let item = TheNodeUIItem::Markdown("desc".into(), fl!("action_clear_tile_desc"));
        nodeui.add_item(item);

        Self {
            id: TheId::named(&fl!("action_clear_tile")),
            nodeui,
        }
    }

    fn id(&self) -> TheId {
        self.id.clone()
    }

    fn info(&self) -> String {
        fl!("action_clear_tile_desc")
    }

    fn role(&self) -> ActionRole {
        ActionRole::Dock
    }

    fn accel(&self) -> Option<TheAccelerator> {
        None
    }

    fn is_applicable(&self, map: &Map, _ctx: &mut TheContext, _server_ctx: &ServerContext) -> bool {
        if map.selected_sectors.is_empty()
            && map.selected_geometry_faces.is_empty()
            && map.selected_geometry_objects.is_empty()
        {
            return false;
        }
        // match server_ctx.editor_view_mode {
        //     EditorViewMode::D2 => server_ctx.editing_surface.is_none(),
        //     _ => true,
        // }
        true
    }

    fn apply(
        &self,
        map: &mut Map,
        _ui: &mut TheUI,
        _ctx: &mut TheContext,
        server_ctx: &mut ServerContext,
    ) -> Option<ProjectUndoAtom> {
        let mut changed = false;
        let prev = map.clone();

        for sector_id in &map.selected_sectors.clone() {
            if let Some(sector) = map.find_sector_mut(*sector_id) {
                if sector.properties.contains("source") {
                    sector.properties.remove("source");
                    changed = true;
                }
            }
        }

        let selected_geometry_faces = map.selected_geometry_faces.clone();
        if selected_geometry_faces.is_empty() {
            for object_id in map.selected_geometry_objects.clone() {
                changed |= crate::utils::clear_surface_source_on_geometry_object(map, object_id);
            }
        } else {
            for (object_id, face_index) in selected_geometry_faces {
                changed |=
                    crate::utils::clear_surface_source_on_geometry_face(map, object_id, face_index);
            }
        }

        if changed {
            map.update_surfaces();
            RUSTERIX.write().unwrap().set_dirty();
            RUSTERIX.write().unwrap().set_overlay_dirty();
            Some(ProjectUndoAtom::MapEdit(
                server_ctx.pc,
                Box::new(prev),
                Box::new(map.clone()),
            ))
        } else {
            None
        }
    }

    fn params(&self) -> TheNodeUI {
        self.nodeui.clone()
    }

    fn handle_event(
        &mut self,
        event: &TheEvent,
        _project: &mut Project,
        _ui: &mut TheUI,
        _ctx: &mut TheContext,
        _server_ctx: &mut ServerContext,
    ) -> bool {
        self.nodeui.handle_event(event)
    }
}
