<?php

if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * Upgrade all modules
 *
 * @author Igor Ratsun
 */
class Upgrade extends \MX_Controller
{

    protected $modules_to_upgrade = array();
    protected $modules_versions = array();

    public function __construct()
    {
        parent::__construct();

        // Load main language file
        $this->load->library('gettext_language');
        $this->gettext_language->load(FCPATH . 'application/language/' . $this->config->item('language') . '.po');

        if (!$this->input->is_cli_request()) {
            $this->load->library('ciext/admin_lib');
            // Acceess check
            if (!$this->rt_user->isAllowed('system', 'module_manager')) {
                $this->admin_lib->show_denied();
            }
        }
        
        // Load AbstractUpgrade class
        if (!class_exists('Abstract_upgrade')) {
            class_alias('Ciext\Migration\AbstractUpgrade', 'Abstract_upgrade');
        }
    }

    public function index()
    {
        $data = array(
            array(
                $this->lang->line('Module'),
                $this->lang->line('Before upgrade version'),
                $this->lang->line('Current version'),
                $this->lang->line('Upgraded')
            )
        );
        foreach ($this->get_modules_to_upgrade() as $module_name) {
            $old_v = $this->get_module_version($module_name);
            $new_v = $this->upgrade($module_name);
            $data[] = array(
                $module_name,
                $old_v,
                $new_v,
                ($old_v == $new_v ? $this->lang->line('No') : $this->lang->line('Yes'))
            );
        }

        // CLI renderer
        if ($this->input->is_cli_request()) {
            foreach ($data as $item) {
                echo PHP_EOL . implode(' | ', $item);
            }
            die(PHP_EOL);
        }

        $this->load->library('table')->set_template(array(
            'table_open' => '<table class="table table-bordered table_over main_table table-hover">'
        ));

        $content = array(
            'title'   => $this->lang->line('Upgrade system'),
            'content' => $this->table->generate($data)
        );

        return $this->admin_lib->show($content);
    }

    public function upgrade($module_name = '')
    {
        if (!in_array($module_name, $this->get_modules_to_upgrade())) {

            return 0;
        }

        $this->load->config($module_name . '/upgrade');
        $current_ver = $this->get_module_version($module_name);
        $versions = $this->config->item('upgrade_' . $module_name);
        if (!empty($versions) && is_array($versions)) {
            foreach ($versions as $ver) {
                if ($ver['version'] == $current_ver) {
                    $new_ver = $this->load->library($ver['library'])->up();
                    $this->set_module_version($module_name, $new_ver);
                    // Up version again
                    return ($new_ver != $current_ver) ? $this->upgrade($module_name) : $current_ver;
                }
            }
        }

        return $current_ver;
    }

    protected function get_modules_to_upgrade()
    {
        if (empty($this->modules_to_upgrade)) {
            $all_modules = array();
            foreach (array_keys($this->config->item('modules_locations')) as $loc) {
                $tmp = scandir($loc);
                foreach ($tmp as $mod_name) {
                    if (!is_dir($loc . $mod_name)) {
                        continue;
                    }
                    if (file_exists($loc . $mod_name . '/config/upgrade.php')) {
                        $all_modules[] = $mod_name;
                    }
                }
                $all_modules = array_unique($all_modules);
            }
            $this->modules_to_upgrade = $all_modules;
        }

        return $this->modules_to_upgrade;
    }

    protected function get_module_version($module_name = '')
    {
        $m_vers = $this->get_modules_versions();

        return isset($m_vers[$module_name]) ? $m_vers[$module_name] : 0;
    }

    protected function set_module_version($module_name, $version)
    {
        if (empty($version)) {
            $version = 0;
        }

        $vers = $this->get_modules_versions();
        $vers[$module_name] = $version;

        // Set new module version

        $this->get_system_config()->set_config(array_merge($this->get_system_config()->get_config(), array('modules_versions' => json_encode($vers))));

        // Update cache
        $this->modules_versions[$module_name] = $version;

        return $this->modules_versions[$module_name];
    }

    protected function get_system_config()
    {
        $this->load->library('ciext/configurator');

        return new configurator('system');
    }

    protected function get_modules_versions()
    {
        if (empty($this->modules_versions)) {
            $vers = $this->get_system_config()->item('modules_versions');
            $this->modules_versions = !empty($vers) ? json_decode($vers, true) : array();
        }

        return $this->modules_versions;
    }

}
