<?php
/**
 * @package    pixelcms_articles
 *
 * @author     christophf <your@email.com>
 * @copyright  A copyright
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       http://your.url.com
 */

use Joomla\CMS\Installer\InstallerAdapter;

defined('_JEXEC') or die;

/**
 * Pixelcms_articles script file.
 *
 * @package     A package name
 * @since       1.0
 */
class Com_Pixelcms_articlesInstallerScript
{
    protected $name;
    protected $oldParams;
    protected $newParams;
    protected $parent;
    protected $adapter;
	/**
	 * Constructor
	 *
	 * @param   JAdapterInstance  $adapter  The object responsible for running this script
	 */
	public function __construct(InstallerAdapter $adapter) {
	    $this->name = strtolower($adapter->getName());
	    $this->oldParams = $this->getParams();
        $this->newParams = $this->getManifest($adapter);
        $this->parent = $adapter->getParent();
        $this->adapter = $adapter;
    }

	/**
	 * Called before any type of action
	 *
	 * @param   string  $route  Which action is happening (install|uninstall|discover_install|update)
	 * @param   JAdapterInstance  $adapter  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function preflight($route, InstallerAdapter $adapter) { }

	/**
	 * Called after any type of action
	 *
	 * @param   string  $route  Which action is happening (install|uninstall|discover_install|update)
	 * @param   JAdapterInstance  $adapter  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function postflight($route, InstallerAdapter $adapter) {}

	/**
	 * Called on installation
	 *
	 * @param   JAdapterInstance  $adapter  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function install(InstallerAdapter $adapter) {}

	/**
	 * Called on update
	 *
	 * @param  $adapter  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function update(InstallerAdapter $adapter) {
        $tmpPath = $this->parent->getPath('source');
        $updates = $this->getUpdateScripts($tmpPath);

        $db = JFactory::getDbo();
        $db->transactionStart(true);
        try {
            $this->runUpdateScripts($updates);
        } catch (Exception $e) {
            \JFactory::getApplication()->enqueueMessage($e->getMessage(), 'Error');
            $db->transactionRollback(true);
            return false;
        }
        $db->transactionCommit(true);
        return true;
    }

	/**
	 * Called on uninstallation
	 *
	 * @param   JAdapterInstance  $adapter  The object responsible for running this script
	 */
	public function uninstall(InstallerAdapter $adapter) {}

    private function getUpdateScripts($path)
    {
        $currentVersion = $this->oldParams->version;
        $newVersion = $this->newParams->version;

        return array_filter(glob("$path/upgrades/*.php"), function($upgrade) use ($currentVersion, $newVersion) {
            if (!preg_match('/\d+\.\d+\.\d+/', $upgrade, $matches)) return false;
            return version_compare($matches[0], $newVersion, '<=') && version_compare($matches[0], $currentVersion, '>');
        });
	}

    private function runUpdateScripts($upgrades)
    {
        foreach ($upgrades as $upgrade) {
            require_once $upgrade;

            $class =  $this->getUpdateClassname($upgrade);
            (new $class($this->adapter))->run();
        }
	}

    private function getUpdateClassname($upgrade)
    {
        preg_match('/\d+\.\d+\.\d+/', $upgrade, $matches);
        return "upgrade_". str_replace('.', '_', $matches[0]);
	}

    private function getParams() {
        $db = JFactory::getDbo();
        $db->setQuery("SELECT manifest_cache FROM #__extensions WHERE name = \"$this->name\"");
        $manifest = json_decode( $db->loadResult(), false );
        return $manifest;
    }

    public function getManifest(InstallerAdapter $adpater)
    {
        return json_decode(json_encode($adpater->getManifest()));
    }
}
