<?php
namespace app;

use RuntimeException;

use app\utils\Str;
use app\utils\RRException;

class App {
    /**
     * 用于判断类是否存在
     */
    protected $classMap = array();

    /**
     * 运行控制器和方法
     * @throws \Exception
     */
    public function run()
    {
        $request = Request::getInstance();

        try {
            // 实例化控制器
            $instance = $this->makeController($request->controller);
        } catch (RuntimeException $e) {
            throw new RRException($e->getMessage(), 404);
        }

        $action = $request->actionName;

        if (is_callable([$instance, $action])) {
            $instance->$action();
        } else {
            // 操作不存在
            throw new RRException('method not exists:'.get_class($instance) . '->' . $action . '()', 404);
        }
    }

    public function makeController(string $controller, bool $newInstance = false)
    {
        $class =  'app' . '\\' . 'controller' . '\\' . $controller;
        if (class_exists($class)) {
            if (isset($this->classMap[$class]) && !$newInstance) {
                return $this->classMap[$class];
            }

            $instance = new $class;

            if (!$newInstance) {
                $this->classMap[$class] = $instance;
            }
            
            return $instance;            
        } else {
            throw new RuntimeException('class not exists:' . $class);
        }
    }
}
