include maths::sqrt

trait AsUnit {
    fn unit(self) -> Self;
}

class Point2 {
    let x: isize,
    let y: isize,

    fn len(self) -> isize {
        sqrt(self.x * self.x + self.y * self.y)
    }
}

// can inherit from a single class + many traits
class Point3: Point2 + AsUnit {
    let z: isize,`

    fn len(self) -> isize {
        // implicit return of internal expressions
        sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
    }

    fn AsUnit.unit(self) -> Self {
        let len = self.len();
        Self {
            x: self.x / len,
            y: self.y / len,
            z: self.y / len,
        }
    }
}

fn do_matches(val: AsUnit) -> bool {

    // can use kotlin-style "is" syntax to find sub-classes and implementors.
    if match val {
        is Point3 => true, // only Point3 as it has no subclasses.
                           // this also implicitly downcasts us to a Point3 so we can use methods specific to this class!
        is Point2 => true, // returns true for Point2 and Point3 as it is a subclass
        is AsUnit => true, // always true.
    } { return true; }

    unreachable()           // this should probably crash the program

    // we can match against any boolean expression. this lazily evaluates each arm one by one.
    match {
        do_some_processing() == 1 => println("success!") { style => style.colour = Colour::Red }
        something_else() == 1 => println!("success") // we can omit the trailing lambda when it's

        // alternative syntax for the same thing as above!
        val is Point3 => { return true; }
        val is AsUnit => { return true; }
        false == true => { return false; }
    };



    // of course normal rust matches also apply
}


/* uilib.dscx */

class UiBuilder {
    ...
    fn text_entry() -> Interaction
}

class Interaction {
    fn clicked() -> bool;
}

/* app.dscx */

pub enum Action {
    SubmitForm(PasswordForm)
}

class PasswordForm {
    let username: String,
    let password: String,
}


class UserInterface {
    const MESSAGE: str = "Run Emulator";
    let form: PasswordForm;
    let state: EmulatorState;

    fn new(state: EmulatorState) -> Self {
        Self {
            form: PasswordForm {
                username: String::new(),
                password: String::new()
            },
            state
        }
    }

    fn ui(self, ui: UiBuilder) -> Action {

        ui_lib::Form(self.form, ui, "login") { form, ui ->
            ui.text_entry(form.username) { view ->
                view.placeholder = "enter username";
            }

            ui.text_entry(form.password); // also acceptable syntax. placeholder has a default value!

            if ui.button("Submit").clicked() {
                return Action::SubmitForm(form);
            }
        }

        ui.vertical {
            my_lib::StatusIndicator(self.state.status, ui);

            if ui.button("Run Emulator").clicked() {
                self.state.run();
            }
        }

    }
}

