#include "wxmain.hpp"
 
 #include <wx/filename.h>
+#include <wx/filedlg.h>
 #include <wx/menu.h>
 #include <wx/sizer.h>
 
+enum Id {
+    Single = 1,
+    ConnectDevice,
+    UploadFilter,
+    RenderTimer,
+
+    MFileNew,
+    MFileOpen,
+    MFileSave,
+    MFileSaveAs,
+    MRunConnect,
+    MRunStart,
+    MRunStartMeasure,
+    MRunCompile,
+    MRunUpload
+};
+
 MainFrame::MainFrame() : wxFrame(nullptr, -1, "Hello world", wxPoint(50, 50), wxSize(640, 800))
 {
     auto menubar = new wxMenuBar;
     auto menuFile = new wxMenu;
+    menuFile->Append(MFileNew, "&New");
+    menuFile->Append(MFileOpen, "&Open");
+    menuFile->Append(MFileSave, "&Save");
+    menuFile->Append(MFileSaveAs, "Save &As");
+    auto menuRun = new wxMenu;
+    menuRun->Append(MRunConnect, "&Connect");
+    menuRun->AppendSeparator();
+    menuRun->Append(MRunStart, "&Start");
+    menuRun->Append(MRunStartMeasure, "Start with &Measure");
+    menuRun->Append(wxID_ANY, "Last time:")->Enable(false);
+    menuRun->AppendSeparator();
+    menuRun->Append(MRunCompile, "&Compile code");
+    menuRun->Append(MRunUpload, "&Upload code");
+
     menubar->Append(menuFile, "&File");
+    menubar->Append(menuRun, "&Run");
     SetMenuBar(menubar);
 
     auto window = new wxBoxSizer(wxVERTICAL);
 
     m_render_timer = new wxTimer(this, Id::RenderTimer);
 
+    Bind(wxEVT_MENU, &MainFrame::onFileNew, this, Id::MFileNew);
+    Bind(wxEVT_MENU, &MainFrame::onFileOpen, this, Id::MFileOpen);
+    Bind(wxEVT_MENU, &MainFrame::onFileSave, this, Id::MFileSave);
+    Bind(wxEVT_MENU, &MainFrame::onFileSaveAs, this, Id::MFileSaveAs);
+
     Bind(wxEVT_BUTTON, &MainFrame::onSinglePressed, this, Id::Single);
     Bind(wxEVT_BUTTON, &MainFrame::onUploadPressed, this, Id::UploadFilter);
     Bind(wxEVT_BUTTON, &MainFrame::onConnectPressed, this, Id::ConnectDevice);
         //this->RefreshRect(m_signal_area->GetRect());
 
         //button->SetLabel("Run");
-        button->SetLabel(wxString::Format(wxT("%u"), m_device->continuous_start_get_measurement()));
+        button->SetLabel(wxString::Format(wxT("Run (%u)"),
+                         m_device->continuous_start_get_measurement()));
     }
 }
 
         wxT("void char short int long auto float double unsigned signed "
             "volatile static const constexpr constinit consteval "
             "virtual final noexcept public private protected"));
-    m_text_editor->SetText(
-R"cpp(adcsample_t *process_data(adcsample_t *samples, unsigned int size)
-{
-    return samples;
-}
-)cpp");
+    wxCommandEvent dummy;
+    onFileNew(dummy);
 }
 
 static const char *makefile_text = R"make(
         return "";
 }
 
+void MainFrame::onFileNew([[maybe_unused]] wxCommandEvent&)
+{
+    m_open_file_path = "";
+    m_text_editor->SetText(
+R"cpp(adcsample_t *process_data(adcsample_t *samples, unsigned int size)
+{
+    return samples;
+}
+)cpp");
+}
+
+void MainFrame::onFileOpen([[maybe_unused]] wxCommandEvent&)
+{
+    wxFileDialog openDialog(this, "Open filter file", "", "",
+                            "C++ source file (*.cpp)|*.cpp",
+                            wxFD_OPEN | wxFD_FILE_MUST_EXIST);
+
+    if (openDialog.ShowModal() != wxID_CANCEL) {
+        if (wxFileInputStream file_stream (openDialog.GetPath()); file_stream.IsOk()) {
+            auto size = file_stream.GetSize();
+            auto buffer = new char[size];
+            if (file_stream.ReadAll(buffer, size)) {
+                m_open_file_path = openDialog.GetPath();
+                m_text_editor->SetText(buffer);
+            }
+            delete[] buffer;
+        }
+    }
+}
+
+void MainFrame::onFileSave(wxCommandEvent& ce)
+{
+    if (m_open_file_path.IsEmpty()) {
+        onFileSaveAs(ce);
+    } else {
+        if (wxFile file (m_open_file_path, wxFile::write); file.IsOpened()) {
+            file.Write(m_text_editor->GetText());
+            file.Close();
+        }
+    }
+}
+
+void MainFrame::onFileSaveAs([[maybe_unused]] wxCommandEvent& ce)
+{
+    wxFileDialog saveDialog(this, "Save filter file", "", "",
+                            "C++ source file (*.cpp)|*.cpp",
+                            wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
+
+    if (saveDialog.ShowModal() != wxID_CANCEL) {
+        if (wxFile file (saveDialog.GetPath(), wxFile::write); file.IsOpened()) {
+            file.Write(m_text_editor->GetText());
+            file.Close();
+            m_open_file_path = saveDialog.GetPath();
+        }
+    }
+}
+
 
 
 class MainFrame : public wxFrame
 {
-    enum Id {
-        Single = 1,
-        ConnectDevice,
-        UploadFilter,
-        RenderTimer
-    };
+public:
+    MainFrame();
+    
+    void onPaint(wxPaintEvent& pe);
+    void onSinglePressed(wxCommandEvent& ce);
+    void onConnectPressed(wxCommandEvent& ce);
+    void onUploadPressed(wxCommandEvent& ce);
+    void onRenderTimer(wxTimerEvent& te);
+
+    void onFileNew(wxCommandEvent&);
+    void onFileOpen(wxCommandEvent&);
+    void onFileSave(wxCommandEvent&);
+    void onFileSaveAs(wxCommandEvent&);
+
+    void doSingle();
+    void updateDrawing();
 
+private:
     bool m_is_rendering = false;
     wxTimer *m_render_timer = nullptr;
     wxComboBox *m_device_combo = nullptr;
     wxStyledTextCtrl *m_text_editor = nullptr;
     wxControl *m_signal_area = nullptr;
+    wxString m_open_file_path;
 
     stmdsp::device *m_device = nullptr;
     std::future<std::vector<stmdsp::adcsample_t>> m_device_samples_future;
     bool tryDevice();
     void prepareEditor();
     wxString compileEditorCode();
-
-public:
-    MainFrame();
-    
-    void onPaint(wxPaintEvent& pe);
-    void onSinglePressed(wxCommandEvent& ce);
-    void onConnectPressed(wxCommandEvent& ce);
-    void onUploadPressed(wxCommandEvent& ce);
-    void onRenderTimer(wxTimerEvent& te);
-
-    void doSingle();
-    void updateDrawing();
 };
 
 #endif // WXMAIN_HPP_