// TODO: Define a new `Order` type.
//   It should keep track of three pieces of information: `product_name`, `quantity`, and `unit_price`.
//   The product name can't be empty and it can't be longer than 300 bytes.
//   The quantity must be strictly greater than zero.
//   The unit price is in cents and must be strictly greater than zero.
//   Order must include a method named `total` that returns the total price of the order.
//   Order must provide setters and getters for each field.
//
// Tests are located in a different place this time—in the `tests` folder.
// The `tests` folder is a special location for `cargo`. It's where it looks for **integration tests**.
// Integration here has a very specific meaning: they test **the public API** of your project.
// You'll need to pay attention to the visibility of your types and methods; integration
// tests can't access private or `pub(crate)` items.

pub struct Order {
    product_name: String,
    quantity: u32,
    unit_price: u32,
}

impl Order {
    fn cName(name: &String) {
        if name.is_empty() {
            panic!("Name must be valid");
        }
        if name.len() > 300 {
            panic!("Name too long");
        }
    }

    fn cQuantity(quantity: &u32) {
        if quantity.eq(&0) {
            panic!("not enough quantity");
        }
    }

    fn cPrice(price: &u32) {
        if price.eq(&0) {
            panic!("invalid price");
        }
    }

    pub fn total(&self) -> u32 {
        self.unit_price * self.quantity
    }

    pub fn new(name: String, quantity: u32, price: u32) -> Order {
        Order::cName(&name);
        Order::cPrice(&price);
        Order::cQuantity(&quantity);
        Order {
            product_name: name,
            quantity,
            unit_price: price,
        }
    }

    pub fn product_name(&self) -> String {
        self.product_name.clone()
    }

    pub fn quantity(&self) -> &u32 {
        &self.quantity
    }

    pub fn unit_price(&self) -> &u32 {
        &self.unit_price
    }

    pub fn set_product_name(&mut self, name: String) {
        Order::cName(&name);
        self.product_name = name;
    }

    pub fn set_quantity(&mut self, quantity: u32) {
        Order::cQuantity(&quantity);
        self.quantity = quantity;
    }

    pub fn set_unit_price(&mut self, price: u32) {
        Order::cPrice(&price);
        self.unit_price = price;
    }
}
