<?php

abstract class Movie {

    protected $name;
    protected $budget;
    protected $cast = [];
    protected $director;

    public function __construct (string $name) {
        $this->name = $name;
    }

    public final function publish () {
        $this->raiseMoney();
        $this->castActors();
        $this->castDirector();
        $this->promote();
    }

    abstract protected function raiseMoney ();

    abstract protected function castActors ();

    abstract protected function castDirector ();

    protected function promote () {
        $actors = implode(", ", $this->cast);
        echo "New movie '{$this->name}' directed by {$this->director}. Starring {$actors} and budget of \${$this->budget}!" . PHP_EOL;
    }
}


class ComedyMovie extends Movie {

    const AVAILABLE_DIRECTORS = ['Edgar Wright', 'Kevin Smith'];
    const AVAILABLE_ACTORS = ['Jim Carrey', 'Eddie Murphy', 'Steve Carell'];
    const NUM_ROLES = 2;

    protected function raiseMoney () {
        $this->budget = 500000;
    }

    protected function castActors () {
        $this->cast[] = 'Adam Sandler';
        $this->cast[] = self::AVAILABLE_ACTORS[array_rand(self::AVAILABLE_ACTORS)];
    }

    protected function castDirector () {
        $this->director = self::AVAILABLE_DIRECTORS[array_rand(self::AVAILABLE_DIRECTORS)];
    }
}



class ActionMovie extends Movie {

    const AVAILABLE_DIRECTORS = ['Michael Bay', 'James Cameron', 'Steven Spielberg'];
    const AVAILABLE_ACTORS = ['Sylvester Stallone', 'Bruce Willis', 'Al Pacino', 'Arnold Schwarzenegger'];
    const NUM_ROLES = 2;

    protected function raiseMoney () {
        $this->budget = 100000;
    }

    protected function castActors () {
        foreach (array_rand(self::AVAILABLE_ACTORS, self::NUM_ROLES) as $actor) {
            $this->cast[] = self::AVAILABLE_ACTORS[$actor];
        }
    }

    protected function castDirector () {
        $this->director = self::AVAILABLE_DIRECTORS[array_rand(self::AVAILABLE_DIRECTORS)];
    }
}


// USAGE
$actionMovie = new ActionMovie("Great action");
$actionMovie->publish();

$comedyMovie = new ComedyMovie("Comedy 2");
$comedyMovie->publish();