<?php

abstract class LSC {

    /*
     * Запускаем работу консоли
     */
    static function Start() {
        $aArgs = $_SERVER['argv'];

        // Если не передана команда выводим помощь
        if (count($aArgs) == 1) {
            echo self::getHelp() . "\n";

            return;
        }

        $sCommandClassName = 'Cmd' . ucwords($aArgs[1]);
        $sCommandClassPath = dirname(__FILE__) . '/commands/' . $sCommandClassName . '.class.php';

        // Существует ли такой класс, а следовательно и команда
        if (file_exists($sCommandClassPath)) {
            // Подключаем класс команды
            require_once $sCommandClassPath;
            /**
             * @var LSC $oCommand
             */
            $oCommand = new $sCommandClassName();
            $oCommand->run($aArgs);
        }
        else {
            die("Command not isset\n");
        }
    }

    /*
     * Отдаем управление вызванной команде
     */
    public function run($aArgs) {
        // Если не передана подкоманда или передана подкоманда help выводим помощь
        if (!isset($aArgs[2]) or $aArgs[2] == 'help') {
            echo $this->getHelp() . "\n";

            return;
        }

        $sMethodName = 'action' . ucwords($aArgs[2]);

        // Оставляем в массиве только параметры для подкоманды
        array_shift($aArgs);
        array_shift($aArgs);
        array_shift($aArgs);

        $this->$sMethodName($aArgs);
    }

    /*
     * Создает массив файлов используемый при копировании
     */
    public function buildFileList($sSourceDir, $sTargetDir, $sBaseDir = '') {
        $aList  = array();
        $handle = opendir($sSourceDir);
        while (($sFile = readdir($handle)) !== false) {
            if ($sFile === '.' || $sFile === '..' || $sFile === '.svn' || $sFile === '.gitignore') {
                continue;
            }

            $sSourcePath = $sSourceDir . DIRECTORY_SEPARATOR . $sFile;
            $sTargetPath = $sTargetDir . DIRECTORY_SEPARATOR . $sFile;

            $sName = ($sBaseDir === '') ? $sFile : $sBaseDir . '/' . $sFile;

            // Строим массив с ключем в виде имени файла или папки, пути к исходнику и пути назначения
            $aList[$sName] = array(
                'source' => $sSourcePath,
                'target' => $sTargetPath
            );

            // Если директория то рекурсивно получаем массив его содержимого и объединяем с главным
            if (is_dir($sSourcePath)) {
                $aList = array_merge($aList, $this->buildFileList($sSourcePath, $sTargetPath, $sName));
            }
        }
        closedir($handle);

        return $aList;
    }

    /*
     * Копирование файлов
     */
    public function copyFiles($fileList) {
        $overwriteAll = false;
        foreach ($fileList as $name => $file) {
            $source = strtr($file['source'], '/\\', DIRECTORY_SEPARATOR);
            $target = strtr($file['target'], '/\\', DIRECTORY_SEPARATOR);

            $callback = isset($file['callback']) ? $file['callback'] : null;
            $params   = isset($file['params']) ? $file['params'] : null;

            if (is_dir($source)) {
                // Проверяем существует ли директория или досоздаем папки
                $this->ensureDirectory($target);
                continue;
            }

            // Если существует коллбэк то вызываем его
            if ($callback !== null) {
                $content = call_user_func($callback, $source, $params);
            }
            // Либо отдаем содержимое исходника без изменений
            else {
                $content = file_get_contents($source);
            }

            // Если файл в папке назначения уже существует
            if (is_file($target)) {
                // Если содержимое старого и нового файла совпадают
                if ($content === file_get_contents($target)) {
                    echo "  unchanged $name\n";
                    continue;
                }

                // Если мы выбрали перезапись в ветке false
                if ($overwriteAll) {
                    echo "  overwrite $name\n";
                }
                else {
                    echo "      exist $name\n";
                    echo "            ...overwrite? [Yes|No|All|Quit] ";

                    // Спрашиваем у пользователя как поступить
                    $answer = trim(fgets(STDIN));
                    if (!strncasecmp($answer, 'q', 1)) {
                        return;
                    }
                    else {
                        if (!strncasecmp($answer, 'y', 1)) {
                            echo "  overwrite $name\n";
                        }
                        else {
                            if (!strncasecmp($answer, 'a', 1)) {
                                echo "  overwrite $name\n";
                                $overwriteAll = true;
                            }
                            else {
                                echo "       skip $name\n";
                                continue;
                            }
                        }
                    }
                }
            }
            // Если файла еще не существует
            else {
                // Досоздаем папки в случае отсутствия
                $this->ensureDirectory(dirname($target));
                echo "   generate $name\n";
            }

            // Создаем файл и записываем в него содержимое
            file_put_contents($target, $content);
        }
    }

    /**
     * Создает родительские папки если они не существуют
     * @param string $directory
     */
    public function ensureDirectory($directory) {
        if (!is_dir($directory)) {
            $this->ensureDirectory(dirname($directory));
            echo "      mkdir " . strtr($directory, '\\', '/') . "\n";
            mkdir($directory);
        }
    }

    /*
     * Выводит помощь и список возможных команд
     */
    public function getHelp() {
        $aList  = array();
        $handle = opendir(dirname(__FILE__) . '/commands/');
        while (($file = readdir($handle)) !== false) {
            if ($file === '.' || $file === '..') {
                continue;
            }
            if (is_file(dirname(__FILE__) . '/commands/' . $file)) {
                $aList[] = strtolower(preg_replace("/^(.*)\.(.*)\.(.*)/i", "$1", $file));
            }
        }
        closedir($handle);

        echo "USAGE:\nls ";

        foreach ($aList as $iKey => $sName) {
            if ($iKey > 0) {
                echo "     ";
            }

            echo substr($sName, 3) . "\n";
        }
    }
}
