use std::any::Any;
use std::path::{Path, PathBuf};
use egui::accesskit::Role::Code;
use egui::{Key, Ui};
use egui_code_editor::{CodeEditor, Syntax};
use egui_file_dialog::FileDialog;
use egui_tiles::TileId;
use crate::ui::components::Component;
use crate::ui::components::editor::{syntax, THEME};
use crate::ui::debugger::Action;
use crate::ui::debugger::panels::TilePane;

pub struct Editor {
    buffer: String,
    filename: Option<PathBuf>,

    editor: CodeEditor,
    dialog: FileDialog,
    visible: bool,
}

impl Default for Editor {
    fn default() -> Self {
        Self {
            buffer: String::new(),
            filename: None,
            editor: CodeEditor::default().with_fontsize(12.0).with_theme(THEME).with_numlines(true),
            dialog: FileDialog::new(),
            visible: false,
        }
    }
}

impl Editor {
    pub fn new_open(path: &Path) -> Self {
        Self {
            buffer: std::fs::read_to_string(path).unwrap(),
            filename: Some(path.to_path_buf()),
            ..Default::default()
        }
    }

    pub fn filename_mut(&mut self) -> &mut Option<PathBuf> {
        &mut self.filename
    }

    pub fn filename(&self) -> Option<&PathBuf> {
        self.filename.as_ref()
    }

    pub fn get_buffer(&mut self) -> &mut String {
        &mut self.buffer
    }
}

impl TilePane for Editor {
    fn title(&self) -> egui::WidgetText {
        self.filename.clone()
            .map(|f| f.file_name().unwrap().to_str().unwrap().into())
            .unwrap_or("New File*".into())
    }

    fn ui(&mut self, ui: &mut Ui, tile_id: TileId) -> Option<Action> {

        egui::Panel::top("panel").show(ui, |ui| {
            if let Some(filename) = self.filename.as_ref() {
                ui.label(filename.display().to_string());
            } else {
                ui.label("New File*");
            }
        });

        let mut action = None;

        self.editor.show(ui, &mut self.buffer, &syntax::dsa());

        if ui.input(|i| i.key_pressed(Key::S) && i.modifiers.ctrl) {
            if let Some(filename) = self.filename.clone() {
                action = Some(Action::SaveFile(filename, tile_id));
            } else {
                action = Some(Action::RequestSaveAs(tile_id));
            }
        };

        action
    }

    fn as_any_mut(&mut self) -> &mut dyn Any { self }

    fn close_requires_confirmation(&mut self, _tile_id: TileId) -> bool {
        true
    }
}