<?php

namespace Ignite\Core\Events\Subscribers\Theme;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

class Scaffold
{
    protected $folder = 'themes';
    /**
     * Register the listeners for the subscriber.
     *
     * @param  \Illuminate\Events\Dispatcher $events
     */
    public function subscribe(\Illuminate\Events\Dispatcher $events)
    {
        $events->listen(
            'ignite.theme.scaffolded',
            'Ignite\Core\Events\Subscribers\Theme\Scaffold@onScaffolded'
        );
    }

    public function onScaffolded(InputInterface $input, OutputInterface $output, $path)
    {
        $base = 'default';
        $name = $input->getArgument('name');

        $output->writeln("Copying files from the $base theme...");
        $this->copyDefaultFiles($name, $base);

        $output->writeln("Customizing your theme...");
        $this->customizeTheme($name, $base);

        $output->writeln("Updating env file...");
        $this->updateEnvFile($name);
    }

    /**
     * Copy the files from the default theme.
     *
     * @param  string $name
     * @param  string $base
     * @return Process
     */
    private function copyDefaultFiles($name, $base = 'default')
    {
        $folder = ($base === 'default') ? 'vendor/ignite/themes' : null;
        $commands = [
            sprintf('mkdir -p %s', $this->getPath($name, 'src/js/')),
            sprintf('cp -r %s %s', $this->getPath($base, 'src/js/*', $folder), $this->getPath($name, 'src/js/')),
            sprintf('mkdir -p %s', $this->getPath($name, 'src/scss/')),
            sprintf('cp %s %s', $this->getPath($base, 'src/scss/style.scss', $folder), $this->getPath($name, 'src/scss/')),
            sprintf('cp %s %s', $this->getPath($base, 'src/scss/_variables.scss', $folder), $this->getPath($name, 'src/scss/')),
            sprintf('cp -r %s %s', $this->getPath($base, 'dist/fonts', $folder), $this->getPath($name, 'dist/fonts')),
            sprintf('cp -r %s %s', $this->getPath($base, 'dist/images', $folder), $this->getPath($name, 'dist/images')),
            sprintf('mkdir -p %s', $this->getPath($name, 'dist/stylesheets')),
            sprintf('mkdir -p %s', $this->getPath($name, 'dist/javascripts')),
            sprintf('cp -r %s %s', $this->getPath($base, 'gulpfile.js', $folder), $this->getPath($name, 'gulpfile.js')),
            sprintf('cp -r %s %s', $this->getPath($base, 'package.json', $folder), $this->getPath($name, 'package.json')),
            sprintf('cp -r %s %s', $this->getPath($base, 'readme.md', $folder), $this->getPath($name, 'readme.md')),
            sprintf('cp -r %s %s', $this->getPath($base, 'views/cms', $folder), $this->getPath($name, 'views/cms')),
            sprintf('cp -r %s %s', $this->getPath($base, 'forms', $folder), $this->getPath($name, 'forms')),
        ];

        $process = new Process(implode(' ; ', $commands), base_path());
        $process->run();
        if (! $process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

        return $process;
    }

    /**
     * Customize the theme files.
     *
     * @param  string $name
     * @param  string $base
     * @return Process
     */
    private function customizeTheme($name, $base = 'default')
    {
        $base = ucfirst(strtolower($base));
        $title = ucfirst(strtolower($name));

        $commands = [
            sprintf('sed -i "1s/%s/%s/" %s', $base, $title, $this->getPath($name, 'readme.md')),
            sprintf('sed -i "39s/\/\///" %s', $this->getPath($name, 'gulpfile.js'))
        ];

        $process = new Process(implode(' ; ', $commands), base_path());
        $process->run();
        if (! $process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

        return $process;
    }

    /**
     * Update the .env file to set the theme.
     *
     * @param  string $name
     * @return Process
     */
    private function updateEnvFile($name)
    {
        $command = sprintf('sed -i "s/APP_THEME_ACTIVE=[a-zA-Z0-9_]*/APP_THEME_ACTIVE=%s/" .env', $name);
        $process = new Process($command, base_path());
        $process->run();
        if (! $process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

        return $process;
    }

    /**
     * Get the path to a directory in context of the current theme.
     *
     * @param  string $name
     * @param  string $path
     * @param  mixed  $folder
     * @return string
     */
    private function getPath($name, $path = null, $folder = null)
    {
        $folder = is_null($folder) ? $this->folder : $folder;
        return base_path(
            $folder . DIRECTORY_SEPARATOR .
            $name .
            (is_null($path) ? '' : DIRECTORY_SEPARATOR . $this->normalizePath($path))
        );
    }

    /**
     * Normalize the path for use across different OSs.
     *
     * @param  string $path
     * @return string
     */
    private function normalizePath($path)
    {
        return str_replace('/', DIRECTORY_SEPARATOR, $path);
    }
}