<?php
/**
 * Controller for installation
 *
 * This file is part of Zoph.
 *
 * Zoph is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Zoph is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with Zoph; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @package Zoph
 * @author Jeroen Roos
 */

namespace install;

use db\db;
use db\install;
use db\exception as dbException;
use tables\collection as allTables;
use conf\conf;
use configurationException;
use generic\controller as genericController;
use requirements;
use settings;
use template\block;
use user;
use auth\validator;
use web\request;


/**
 * Controller for migrations
 */
class controller extends genericController {
    protected static $viewAdminuser     = view\adminuser::class;
    protected static $viewConfig        = view\config::class;
    protected static $viewDatabase      = view\database::class;
    protected static $viewDbcheck       = view\dbcheck::class;
    protected static $viewDbpass        = view\dbpass::class;
    protected static $viewDisplay       = view\display::class;
    protected static $viewFinish        = view\finish::class;
    protected static $viewInifile       = view\inifile::class;
    protected static $viewIniform       = view\iniform::class;
    protected static $viewRequirements  = view\requirements::class;
    protected static $viewTables        = view\tables::class;

    /** @var array Actions that can be used in this controller
     *
     * The installation goes through the following stages:
     * display -> requirements -> iniform -> inifile -> dbcheck -> dbpass -> database -> tables -> adminuser -> config -> finish
     */
    protected   $actions    = array(
        "display",
        "requirements",
        "iniform",
        "inifile",
        "dbcheck",
        "dbpass",
        "database",
        "tables",
        "adminuser",
        "config",
        "finish"
    );

    /**
     * Create a controller using a web request
     * @param request request
     */
    public function __construct(request $request) {
        parent::__construct($request);
        $this->doAction();
    }

    /**
     * Do action 'display'
     */
    public function actionDisplay() {
        $this->view = new static::$viewDisplay($this->request);
    }

    /**
     * Do action 'requirements'
     */
    public function actionRequirements() {
        $requirements = new requirements\check();
        $requirements->doChecks();

        $this->view = new static::$viewRequirements($this->request);
        $this->view->addRequirements($requirements);
    }

    /**
     * Do action 'iniform'
     */
    public function actionIniform() {
        $this->view = new static::$viewIniform($this->request);
    }

    /**
     * Do action 'inifile'
     */
    public function actionInifile() {
        $inifile =
            "[" . $this->request->name . "]\n" .
            "    db_host = \"" . $this->request->db_host . "\"\n" .
            "    db_name = \"" . $this->request->db_name . "\"\n" .
            "    db_user = \"" . $this->request->db_user . "\"\n" .
            "    db_pass = \"" . $this->request->db_pass . "\"\n" .
            "    db_prefix = \"" . $this->request->db_prefix . "\"\n" .
            "    php_location = \"" . settings::$php_loc . "\"\n\n";

        $this->view = new static::$viewInifile($this->request);
        $this->view->setInifile($inifile);
    }

    /**
     * Do action 'dbcheck'
     * This checks if the INI file is correct
     * and whether or not the database already exists
     */
    public function actionDbcheck() {
        $this->view = new static::$viewDbcheck($this->request);

        try {
            settings::loadINI();
        } catch (configurationException $e) {
            $this->view->setError("INI file incorrect. " . $e->getMessage());
        }

        try {
            foreach (array("photos", "albums", "categories", "places", "people") as $table) {
                $dbinfo[$table] = (new \db\select($table))->addFunction(array("count" => "COUNT(*)"))->getCount();
            }
            $this->view->setDatabaseInfo($dbinfo);
        } catch (dbException $e) {
            // Exception because database does not exist
            // in this case, this is expected.
        }

    }

    /**
     * Do action 'dbpass'
     */
    public function actionDbPass() {
        $this->view = new static::$viewDbpass($this->request);

    }

    /**
     * Do action 'database'
     */
    public function actionDatabase() {
        $this->view = new static::$viewDatabase($this->request);

        $dbLogin = db::getLoginDetails();

        $dbuser = $this->request["user"] ?? $dbLogin["user"];
        $dbpass = $this->request["admin_pass"] ?? $dbLogin["pass"];

        $install = new install($dbuser, $dbpass);
        $install->user();
        $install->create();
        $install->grant();
        $this->view->setResults($install->getResults());
    }

    /**
     * Do action 'tables'
     */
    public function actionTables() {
        $this->view = new static::$viewTables($this->request);

        $results = array();

        foreach (new allTables() as $table) {
            $table->create();
            $table->addData();
            $results[]=$table->getResult();
        }

        $this->view->setResults($results);
    }

    /**
     * Do action 'adminuser'
     */
    public function actionAdminuser() {
        $this->view = new static::$viewAdminuser($this->request);
    }

    /**
     * Do action 'config'
     */
    public function actionConfig() {
        $this->view = new static::$viewConfig($this->request);

        $password = $this->request["admin_pass"];

        $user = user::getByName("admin");
        $user->set("password", validator::hashPassword($password));
        $user->update();
    }

    /**
     * Do action 'finish'
     */
    public function actionFinish() {
        $this->view = new static::$viewFinish($this->request);
        conf::loadFromRequestVars($this->request->getRequestVars());
    }
}
