//! CalcPad — native Windows (and cross-platform) notepad calculator.
//!
//! Built with iced and the calcpad-engine. Two-column layout:
//! editable text on the left, live-evaluated results on the right.
//! GPU-accelerated rendering via wgpu with automatic tiny-skia fallback.

mod evaluator;
mod theme;
mod ui;

use evaluator::LineResult;
use iced::widget::{column, container, row, text_editor, vertical_rule};
use iced::{Element, Font, Length};

fn main() -> iced::Result {
    iced::application("CalcPad", CalcPad::update, CalcPad::view)
        .window_size((960.0, 640.0))
        .run()
}

// ---------------------------------------------------------------------------
// Application state
// ---------------------------------------------------------------------------

/// Top-level application state.
struct CalcPad {
    /// The editor content (left pane).
    content: text_editor::Content,
    /// Cached per-line results (right pane).
    results: Vec<LineResult>,
    /// Current line count (for the header status).
    line_count: usize,
}

impl Default for CalcPad {
    fn default() -> Self {
        Self {
            content: text_editor::Content::new(),
            results: vec![LineResult {
                display: String::new(),
                is_error: false,
            }],
            line_count: 1,
        }
    }
}

// ---------------------------------------------------------------------------
// Messages
// ---------------------------------------------------------------------------

#[derive(Debug, Clone)]
enum Message {
    /// The user interacted with the text editor.
    EditorAction(text_editor::Action),
}

// ---------------------------------------------------------------------------
// Update & View
// ---------------------------------------------------------------------------

impl CalcPad {
    fn update(&mut self, message: Message) {
        match message {
            Message::EditorAction(action) => {
                let is_edit = action.is_edit();
                self.content.perform(action);

                if is_edit {
                    self.re_evaluate();
                }
            }
        }
    }

    fn view(&self) -> Element<'_, Message> {
        // -- Header --
        let header = ui::header::view::<Message>(self.line_count);

        // -- Left: text editor --
        let editor = text_editor(&self.content)
            .on_action(Message::EditorAction)
            .font(Font::MONOSPACE)
            .height(Length::Fill)
            .style(theme::editor_style);

        let editor_pane = container(editor)
            .width(Length::FillPortion(3))
            .height(Length::Fill)
            .style(theme::editor_pane);

        // -- Right: results column --
        let results_view = ui::results_column::view::<Message>(&self.results);

        let results_pane = container(results_view)
            .width(Length::FillPortion(2))
            .height(Length::Fill)
            .style(theme::results_pane);

        // -- Assemble --
        let body = row![editor_pane, vertical_rule(1), results_pane]
            .height(Length::Fill);

        column![header, body].height(Length::Fill).into()
    }

    // -----------------------------------------------------------------------
    // Helpers
    // -----------------------------------------------------------------------

    /// Re-evaluate all lines through the engine and cache results.
    fn re_evaluate(&mut self) {
        let source = self.content.text();
        self.results = evaluator::evaluate_sheet(&source);
        self.line_count = source.lines().count().max(1);
    }
}
