// Exercise 2: abstract classes and interfaces
//
// Implement:
//   - abstract class Employee: field String name, abstract method
//     double monthlyPay(), concrete method String summary() returning
//     name + " earns " + monthlyPay() + "/month"
//   - class SalariedEmployee extends Employee: field double annualSalary,
//     monthlyPay() returns annualSalary / 12
//   - class HourlyEmployee extends Employee: fields double hourlyRate,
//     double hoursPerMonth, monthlyPay() returns hourlyRate * hoursPerMonth
//   - interface Bonusable with a default method
//     double payWithBonus(double bonus) — cannot know monthlyPay() itself,
//     so it must be combined with an abstract method getBasePay()
//     that implementers provide; payWithBonus returns getBasePay() + bonus
//   - class SalariedEmployee should also implement Bonusable, where
//     getBasePay() delegates to monthlyPay()

public class java_inheritance_and_polymorphism_exercise_2 {

    interface Bonusable {
        double getBasePay();

        default double payWithBonus(double bonus) {
            // TODO: implement
            return 0;
        }
    }

    static abstract class Employee {
        String name;

        Employee(String name) {
            this.name = name;
        }

        abstract double monthlyPay();

        String summary() {
            // TODO: implement
            return null;
        }
    }

    static class SalariedEmployee extends Employee implements Bonusable {
        double annualSalary;

        SalariedEmployee(String name, double annualSalary) {
            super(name);
            this.annualSalary = annualSalary;
        }

        @Override
        double monthlyPay() {
            // TODO: implement
            return 0;
        }

        @Override
        public double getBasePay() {
            // TODO: delegate to monthlyPay()
            return 0;
        }
    }

    static class HourlyEmployee extends Employee {
        double hourlyRate;
        double hoursPerMonth;

        HourlyEmployee(String name, double hourlyRate, double hoursPerMonth) {
            super(name);
            this.hourlyRate = hourlyRate;
            this.hoursPerMonth = hoursPerMonth;
        }

        @Override
        double monthlyPay() {
            // TODO: implement
            return 0;
        }
    }

    // --- self-check: do not modify below this line ---
    public static void main(String[] args) {
        boolean ok = true;

        SalariedEmployee se = new SalariedEmployee("Ada", 120000.0);
        ok &= se.monthlyPay() == 10000.0;
        ok &= se.summary().equals("Ada earns 10000.0/month");
        ok &= se.payWithBonus(500.0) == 10500.0;

        HourlyEmployee he = new HourlyEmployee("Grace", 50.0, 160.0);
        ok &= he.monthlyPay() == 8000.0;
        ok &= he.summary().equals("Grace earns 8000.0/month");

        // abstract class cannot be instantiated directly — this must NOT compile if uncommented:
        // Employee e = new Employee("x");

        System.out.println(ok ? "PASS" : "FAIL");
    }
}
