type CoffeeCup = {
  shots: number;
  hasMilk?: boolean;
  hasSugar?: boolean;
};

*// interface*
interface CoffeeMakerA {
  makeCoffee(shots: number): CoffeeCup;
}

*// Class 1*
*// Parent Class : CoffeeMaker ( 추상 클래스 ) ★*
abstract class CoffeeMaker implements CoffeeMakerA {

  private static BEANS_GRANS_PER_SHOT = 7;

  constructor(private coffeeBeans: number,) {
    this.coffeeBeans = coffeeBeans;
  }

  fillCoffeeBeans(beans: number) {
    if (beans < 0) {
      throw new Error('beans not enoughf');
    }
    this.coffeeBeans += beans;
  }

  private grindBeans(shots: number) {
    console.log(`grinding beans for ${shots}`);
    if (this.coffeeBeans < shots * CoffeeMaker.BEANS_GRANS_PER_SHOT) {
      throw new Error('Not enough coffee beans!');
    }
    this.coffeeBeans -= shots * CoffeeMaker.BEANS_GRANS_PER_SHOT;
  }

  private preheat(): void {
    console.log('heating up...🔥');
  }

	*// 추상 메서드 선언 ★*
  protected abstract extract(shots: number): CoffeeCup;

  public makeCoffee(shots: number): CoffeeCup {
    this.grindBeans(shots);
    this.preheat();
    const coffee = this.extract(shots); *// 자식 클래스에서 extract 함수 오버라이딩*
    const addsugar = this.sugar.addSugar(coffee);
    *return* this.milk.makeMilk(addsugar);
  }
}

*// Class 2 : CoffeeLatteMachine ( 자식 클래스 )*
class CoffeeLatteMachine implements CoffeeMaker {

	constructor(coffeeBeans: number, public serialNumber: string) {
    super(coffeeBeans);
  }

	private steamMilk(): void {
    console.log('Steaming some milk... 🥛');
  }

	*// 추상 메서드 오버라이딩 ★*
	extract(shots: number): CoffeeCup	{
		this.steamMilk():
    console.log(`Pulling ${shots} shots...☕`);
    *return* {
      shots: shots,
      hasMilk: true,
    }
  }
}

*// Class 3 : SweetCoffeeMaker ( 자식 클래스 )*
class SweetcoffeeMaker implements CoffeeMaker {

	*// 추상 메서드 오버라이딩 ★*
	extract(shots: number): CoffeeCup	{
    console.log(`Pulling ${shots} shots...☕`);
    *return* {
      shots: shots,
      hasMilk: false,
    }
  }
}

*// 호출 유형 & 방법 예시 기억해 두기 ★★★*
*// Milk*
const machines = [
	new CoffeeLatteMachine(24, 'ssss-1'),
	new SweetCoffeeMaker(24),
	new CoffeeLatteMachine(24, 'ssss-2'),
	new SweetCoffeeMaker(24),
];
machines.forEach(machine => {
	console.log('----------------------');
	machine.makeCoffee(1);
});