<?php
include "vendor/autoload.php";

// 调试输出
function vd($msg)
{
    print_r($msg);
    echo PHP_EOL;
}

function vde($msg)
{
    vd($msg);
    exit;
}

// 解析参数
function explainArgv($argv)
{
    $args = [];
    foreach ($argv as $value) {
        list($k, $v) = explode('=', $value);
        $k        = ltrim(ltrim(trim($k), '--'), '-');
        $v        = trim($v);
        $args[$k] = $v;
    }
    return $args;
}

function usage()
{
    echo '使用示例:' . PHP_EOL;
    echo 'php ./dump.php -app=shot -split=false' . PHP_EOL;
}

class Dump
{
    // 文件夹路径符
    private static $DS = '/';

    /**
     * @var string
     */
    private $appName;

    /**
     * 是否需要分子目录
     *
     * @var boolean
     */
    private $split = false;

    /**
     * 源文件目录
     */
    private $sourceDir;

    /**
     * 脚本目录
     */
    private $scriptDir;

    /**
     * 导出文件目录
     */
    private $outputDir;

    /**
     * Dump constructor.
     *
     * @param array $args
     */
    public function __construct($args)
    {
//        vd(sprintf("$args: %s", var_export($args, true)));
        if (!isset($args['app'])) {
            vd('参数错误');
            usage();
            exit;
        }
        // 初始化导出参数
        $this->appName = $args['app'];
        if (isset($args['split'])) {
            $this->split = $args['split'];
        }
        $this->sourceDir = __DIR__ . self::$DS . 'projects' . self::$DS . $this->appName . self::$DS . 'source';
        $this->scriptDir = __DIR__ . self::$DS . 'projects' . self::$DS . $this->appName . self::$DS . 'script';
        $this->outputDir = __DIR__ . self::$DS . 'projects' . self::$DS . $this->appName . self::$DS . 'output';

        // 检查目录文件是否缺失
        if (!is_dir($this->sourceDir)) {
            vde('源文件目录缺失:' . $this->sourceDir);
        }
        if (!is_dir($this->scriptDir)) {
            vde('脚本目录缺失:' . $this->scriptDir);
        }
        if (!is_dir($this->outputDir)) {
            vde('输出目录缺失:' . $this->outputDir);
        }
    }

    /**
     * 执行主函数
     */
    public function run()
    {
        // 遍历源目录, 找出所有可执行的文件
        $files     = [];
        $sourceDir = dir($this->sourceDir);
        while ($file = $sourceDir->read()) {
            if ($file == '.' || $file == '..') {
                continue;
            }
            $pathInfo = pathinfo($file);
            // 现在仅支持xlsx文件
            if ($pathInfo['extension'] != 'xlsx') {
                continue;
            }
            $files[] = $pathInfo;
        }
        $sourceDir->close();
        if (empty($files)) {
            vde('源目录为空, 未找到.xlsx文件, 源目录:' . $this->sourceDir);
        }

        // 执行导出
        $success = 0;
        foreach ($files as $fileInfo) {
            if ($this->dump($fileInfo)) {
                ++$success;
            }
        }

        vd(sprintf("导出完成,共[%d]个文件, 成功[%d]个文件.", count($files), $success));


        /*
        // 组装导出目录
        $dumpBase = '..' . self::$DS . '..' . self::$DS . 'output' . self::$DS . $this->appName;
        self::vd($dumpBase);

        // 找到最后一次导出目录
        $lastDumpDir = $this->getLastDumpDir($dumpBase);
        self::vd("Last Dump Dir: " . $lastDumpDir);

        // 获取json文件路径
        $jsonPath = $lastDumpDir . self::$DS . 'PHP' . self::$DS . $this->dumpName . '.json';

        // 读取json文件，并解析成数组
        $json = $this->getJsonData($jsonPath);

        // 写配置文件
        $this->writeData($json, $lastDumpDir, $this->dumpName);

        // 判断此配置文件是否有特殊逻辑
        $methodName = $this->dumpName . '_handler';
        if (method_exists($this, $methodName)) {
            $this->$methodName($json, $lastDumpDir, $this->dumpName);
            self::vd("{$methodName} Done...");
        }

        // 删除json文件
        unlink($jsonPath);

        // 退出
        self::vd("Dump Done ...", true);
        */
    }


    /**
     * 导出表
     *
     * @param array $fileInfo
     * @return bool
     */
    private function dump($fileInfo)
    {
        // 找到文件对应的执行脚本
        $script = $this->scriptDir . self::$DS . $fileInfo['filename'] . '.php';
        if (!file_exists($script)) {
            vd(sprintf('[%s]对应的脚本文件不存在, 脚本文件:%s', $fileInfo['basename'], $script));
            return false;
        }

        // 引入脚本
        include $script;

        // 读取excel文件内容
        $sourceData = $this->getDataFromSource($this->sourceDir . self::$DS . $fileInfo['basename']);
//        vde($sourceData);
        if (count($sourceData) < $dataLine) {
            vd(sprintf('[%s]文件没有数据', $fileInfo['basename']));
            return false;
        }

        // 处理导出列对应的索引
        $indexes = [];
//        vd($sourceData[$columnLine - 1]);
        foreach ($sourceData[$columnLine - 1] as $index => $column) {
            if (isset($columns[$column])) {
                $indexes[$column] = $index;
            }
        }
//        vd($indexes);

        // 普通处理逻辑
        $data = [];
        foreach ($sourceData as $k => $v) {
            // 非数据列不处理
            if ($k < $dataLine - 1) {
                continue;
            }

            $row = [];
            foreach ($columns as $column => $columnType) {
                $columnValue = trim($v[$indexes[$column]]);
                switch ($columnType) {
                    case 'float':
                        $columnValue = floatval($columnValue);
                        break;
                    case 'number':
                        $columnValue = intval($columnValue);
                        break;
                    case 'json':
                        $columnValue = json_decode($columnValue, true);
                        break;
                    default:
                        $columnValue = strval($columnValue);
                        break;
                }
                $row[$column] = $columnValue;
            }
            // 跳过空行
            if (!$row[$keyColumn]) {
                continue;
            }

            $data[$row[$keyColumn]] = $row;
        }

        // 额外处理逻辑
        $handle = $fileInfo['filename'] . '_handle';
        if (function_exists($handle)) {
            $data = $handle($data);
        }

        // 写入文件
        $outputFile = $this->outputDir . self::$DS . $fileInfo['filename'] . '.config.php';
        $this->writeFile($outputFile, $data);

        return true;
    }

    /**
     * @param string $file 源文件地址
     * @return array
     */
    private function getDataFromSource($file)
    {
        $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
        $reader->setReadDataOnly(['Sheet 1']);
        $spreadsheet = $reader->load($file);
        $data        = $spreadsheet->getActiveSheet()->toArray();
        return $data;
    }

    /**
     * 写入php文件
     *
     * @param string $file 写入文件路径
     * @param string $data 写入文件内容
     * @return void
     */
    private function writeFile($file, $data)
    {
        // 写入配置文件
        $configs = var_export($data, true);
        // 整理输出格式
        $config = <<<TXT
<?php
return {$configs};
TXT;

        // 写入导出文件
        file_put_contents($file, $config);
    }
}

/*
 * 使用说明
 * php ./dump.php -app=shot -split=false
 */
// 读取 & 解析命令行参数
array_shift($argv);
$args = explainArgv($argv);
// 执行导出
$dump = new Dump($args);
$dump->run();
