input = $input;
        $this->addStyles($output);
        $this->output = $output;
    }
    /**
     * Change the directory where Codeception should be installed.
     */
    public function initDir($workDir)
    {
        $this->checkInstalled($workDir);
        $this->sayInfo("Initializing Codeception in $workDir");
        $this->createDirectoryFor($workDir);
        chdir($workDir);
        $this->workDir = $workDir;
    }
    /**
     * Override this class to create customized setup.
     * @return mixed
     */
    abstract public function setup();
    /**
     * ```php
     * ask('select the browser of your choice', 'firefox');
     *
     * // propose firefox or chrome possible options
     * $this->ask('select the browser of your choice', ['firefox', 'chrome']);
     *
     * // ask true/false question
     * $this->ask('do you want to proceed (y/n)', true);
     * ```
     *
     * @param $question
     * @param null $answer
     * @return mixed|string
     */
    protected function ask($question, $answer = null)
    {
        $question = "? $question";
        $dialog = new QuestionHelper();
        if (is_array($answer)) {
            $question .= " (" . $answer[0] . ") ";
            return $dialog->ask($this->input, $this->output, new ChoiceQuestion($question, $answer, 0));
        }
        if (is_bool($answer)) {
            $question .= " (y/n) ";
            return $dialog->ask($this->input, $this->output, new ConfirmationQuestion($question, $answer));
        }
        if ($answer) {
            $question .= " ($answer)";
        }
        return $dialog->ask($this->input, $this->output, new Question("$question ", $answer));
    }
    /**
     * Print a message to console.
     *
     * ```php
     * say('Welcome to Setup');
     * ```
     *
     *
     * @param string $message
     */
    protected function say($message = '')
    {
        $this->output->writeln($message);
    }
    /**
     * Print a successful message
     * @param $message
     */
    protected function saySuccess($message)
    {
        $this->say(" $message ");
    }
    /**
     * Print warning message
     * @param $message
     */
    protected function sayWarning($message)
    {
        $this->say(" $message ");
    }
    /**
     * Print info message
     * @param $message
     */
    protected function sayInfo($message)
    {
        $this->say("> $message");
    }
    /**
     * Create a helper class inside a directory
     *
     * @param $name
     * @param $directory
     */
    protected function createHelper($name, $directory)
    {
        $file = $this->createDirectoryFor(
            $dir = $directory . DIRECTORY_SEPARATOR . "Helper",
            "$name.php"
        ) . "$name.php";
        $gen = new Lib\Generator\Helper($name, $this->namespace);
        // generate helper
        $this->createFile(
            $file,
            $gen->produce()
        );
        require_once $file;
        $this->sayInfo("$name helper has been created in $dir");
    }
    /**
     * Create an empty directory and add a placeholder file into it
     * @param $dir
     */
    protected function createEmptyDirectory($dir)
    {
        $this->createDirectoryFor($dir);
        $this->createFile($dir . DIRECTORY_SEPARATOR . '.gitkeep', '');
    }
    protected function gitIgnore($path)
    {
        if (file_exists(self::GIT_IGNORE)) {
            file_put_contents($path . DIRECTORY_SEPARATOR . self::GIT_IGNORE, "*\n!" . self::GIT_IGNORE);
        }
    }
    protected function checkInstalled($dir = '.')
    {
        if (file_exists($dir . DIRECTORY_SEPARATOR . 'codeception.yml') || file_exists($dir . DIRECTORY_SEPARATOR . 'codeception.dist.yml')) {
            throw new \Exception("Codeception is already installed in this directory");
        }
    }
    /**
     * Create an Actor class and generate actions for it.
     * Requires a suite config as array in 3rd parameter.
     *
     * @param $name
     * @param $directory
     * @param $suiteConfig
     */
    protected function createActor($name, $directory, $suiteConfig)
    {
        $file = $this->createDirectoryFor(
            $directory,
            $name
        ) . $this->getShortClassName($name);
        $file .= '.php';
        $suiteConfig['namespace'] = $this->namespace;
        $config = Configuration::mergeConfigs(Configuration::$defaultSuiteSettings, $suiteConfig);
        $actorGenerator = new Lib\Generator\Actor($config);
        $content = $actorGenerator->produce();
        $this->createFile($file, $content);
        $this->sayInfo("$name actor has been created in $directory");
        $actionsGenerator = new Lib\Generator\Actions($config);
        $content = $actionsGenerator->produce();
        $generatedDir = $directory . DIRECTORY_SEPARATOR . '_generated';
        $this->createDirectoryFor($generatedDir, 'Actions.php');
        $this->createFile($generatedDir . DIRECTORY_SEPARATOR . $actorGenerator->getActorName() . 'Actions.php', $content);
        $this->sayInfo("Actions have been loaded");
    }
}