// Import the core angular services.
import { Component } from "@angular/core";

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

// Because an Abstract class has a runtime representation, we can use it as a
// dependency-injection (DI) token in Angular's DI container. And, since each concrete
// class has to implement or extend this abstract base class, it means that the base
// class can act as the "interface" to the behavior as well.
abstract class Greeter {
	abstract greeting() : string;
}

// NOTE: We could have also used "extends Greeter" if Greeter provided base
// functionality that needed to be shared with its concrete classes.
class NiceGreeter implements Greeter {

	public greeting() : string {

		return( "Hello, what a pleasure to meet you." );

	}

}

// NOTE: We could have also used "extends Greeter" if Greeter provided base
// functionality that needed to be shared with its concrete classes.
class MeanGreeter implements Greeter {

	public greeting() : string {

		return( "Hello, you are a doofus!" );

	}

}

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

@Component({
	selector: "my-app",
	providers: [
		// For this application, let's provide the MeanGreeter instance when the
		// Greeter needs to be injected into the App component.
		{
			provide: Greeter,
			useClass: MeanGreeter // <--- Defining the swappable implementation.
		}
	],
	styleUrls: [ "./app.component.css" ],
	template:
	`
		<p>
			<strong>Greeting:</strong> {{ greeting }}
		</p>
	`
})
export class AppComponent {

	public greeting: string;

	// I initialize the app component.
	constructor( greeter: Greeter ) {

		this.greeting = greeter.greeting();

	}

}