<?php
namespace App\Service;

use Stringy\Stringy;

class DBToModel
{
	protected $name;
	protected $db;
	protected $tables;
	
	public function __construct($name = 'mysql')
	{
		$this->name = $name;
		$this->db = \ORM::get_db($name);
	}
	
	public function run()
	{
		$this->getTables();
		foreach ($this->tables as $table) {
			if ($this->createClass($table)) {
				echo 'ok<br />', PHP_EOL;
			}
		}
	}
	protected function getType($type)
	{
		if (strpos($type, '(') !== false) {
			$type = substr($type, 0, strpos($type, '('));
		}
		if (strpos($type, ' ') !== false) {
			$type = substr($type, 0, strpos($type, ' '));
		}
		switch ($type) {
			case 'int':
			case 'float':
			case 'double':
			case 'char':
				return trim($type);
			case 'date':
			case 'datetime':
				return trim(strtolower($type));
			case 'varchar':
			case 'text':
			case 'blob':
				return 'string';
			case 'bigint':
			case 'tinyint':
			case 'enum':
				return 'int';
			default:
				d($type);
		}
	}
	protected function getTables()
	{
		$q = "SHOW TABLES";
		$st = $this->db->query($q);
		$results = $st->fetchAll(\PDO::FETCH_COLUMN);
		$this->tables = [];
		foreach ($results as $result) {
			$this->tables []= $result;
		}
	}
	protected function getColumns($table)
	{
		$q = "SHOW COLUMNS FROM `" . $table . "`";
		$st = $this->db->query($q);
		$results = $st->fetchAll(\PDO::FETCH_OBJ);
		return $results;
	}
	protected function phpDoc($columns)
	{
		$str = ['/**'];
		$str []= ' *';
		foreach ($columns as $column) {
			$str []= ' * @property ' . $this->getType($column->Type) . ' ' . $column->Field;
		}
		$str []= ' *';
		$str []= ' */';
		
		return implode(PHP_EOL, $str);
	}
	protected function className($table)
	{
		$name = Stringy::create($table)->upperCamelize();
		return $name;
	}
	protected function createClass($table)
	{
		$class = '' . $this->className($table);
		$columns = $this->getColumns($table);
		$docs = $this->phpDoc($columns);
		
		$output = ['<?php'];
		$output []= '';
		$output []= $docs;
		$output []= 'class ' . $class . ' extends \\Model';
		$output []= '{';
		$output []= "\tpublic static \$_connection_name = '{$this->name}';";
		$output []= '}';
		$output []= '?>';
		
		//d(implode(PHP_EOL, $output));
		
		$filename = realpath(root() . '/src') . DIRECTORY_SEPARATOR . $class . '.php';
		return file_put_contents($filename, implode(PHP_EOL, $output));
	}
	public function create($namespace, $table)
	{
		$class = '' . $this->className($table);
		$columns = $this->getColumns($table);
		$docs = $this->phpDoc($columns);
		
		$namespace = trim($namespace, '\\');
		
		$output = ['<?php'];
		$output []= 'namespace ' . $namespace . ';';
		$output []= '';
		$output []= $docs;
		$output []= 'class ' . $class . ' extends \\Model';
		$output []= '{';
		$output []= "\tpublic static \$_connection_name = '{$this->name}';";
		$output []= '}';
		$output []= '?>';
		$output = implode(PHP_EOL, $output);
		
		$namespace = explode('\\', $namespace);
		array_shift($namespace);
		$namespace = implode('/', $namespace);
		
		$filename = realpath(root() . '/src/' . $namespace) . DIRECTORY_SEPARATOR . $class . '.php';
		
		$result = [
				'result' => false,
				'filename' => $filename,
				'output' => $output
		];
		if (!file_exists($filename)) {
			$result['result'] = file_put_contents($filename, $output);
		} else {
			$result['result'] = true;
		}
		return json_encode($result);
	}
	public function list()
	{
		$this->getTables();
		$output = [];
		foreach ($this->tables as $table) {
			$output []= ['table' => $table, 'model' => '' . $this->className($table)];
		}
		
		return json_encode(['models' => $output]);
	}
}
?>