<?php

require_once('Helper.php');
require_once('Storage.php');
require_once('Project.php');
require_once('ModulesUpdater.php');
require_once('ThemeBuilder.php');
require_once('Chunk.php');

//set_error_handler('errorCatcher', E_ALL);
//register_shutdown_function('fatalErrorCatcher');

class ExportController 
{
    public function __construct() {}

    public function execute($data)
    {
        $app = JFactory::getApplication('administrator');

        $template_id = $this->_getTemplateId();

        if (isset($data['auto_authorization']) && 1 === (int)$data['auto_authorization']) {
            $user = $data['username'];
            $password = $data['password'];
            $domain = $data['domain'];

            // save user, password and domain to template project
            Project::saveProperty('domain', $domain);
            Project::saveProperty('username', $user);
            Project::saveProperty('password', $password);

            $credentials = array( 'username' => $user, 'password' => $password);

            $app->login($credentials, array('action' => 'core.login.admin'));

            $base = dirname(dirname(dirname(dirname($_SERVER['PHP_SELF']))));
            $return = $base . ($base[strlen($base)-1] !== DS ? DS : '') . 'administrator/';

            $session = JFactory::getSession();
            $registry = $session->get('registry');
            $registry->set('com_templates.edit.style.id', $template_id);

            if ($template_id) {
                $return .= 'index.php?option=com_templates&view=style&layout=edit&id=' .
                    $template_id . '&editor=1&domain=' . urlencode($domain) . '/';
            }
            $app->redirect($return);
        }

        // checking user privileges
        $user = JFactory::getUser();
        $allowedGroups = array('Super Users', '8', 'Administrator', '7');
        $currentGroups = $user->get("groups");
        if (!in_array(array_pop($currentGroups), $allowedGroups)) {
            $session = JFactory::getSession();
            $registry = $session->get('registry');
            $registry->set('com_templates.edit.style.id', $template_id);
            exit('no-rights:Using the Designer requires administrator privileges.');
        }

        echo $this->{$data['action']}($data);
    }

    public function doExport($data)
    {
        return $this->_export($data);
    }
    
    public function saveProject($data) 
    {
        return $this->_export($data);
    }
    
    private function _export($data)
    {
        $info = json_decode($data['info'], true);
        $templateName = $data['template'];
        $chunk = new Chunk();
        $chunk->save($info);

        if ($chunk->last()) {
            $result = json_decode($chunk->complete(), true);
            // icon fonts collection
            $icons = array_key_exists('iconSetFiles', $result) > 0 ? $result['iconSetFiles'] : '';
            // thumbnails collection
            $thumbnails = array_key_exists('thumbnails', $result) > 0 ? $result['thumbnails'] : '';
            // custom images collction
            $images = array_key_exists('images', $result) > 0 ? $result['images'] : '';
            // storage for media files
            $media = array('icons' => $icons, 'thumbnails' => $thumbnails, 'images' => $images);
            $app = JPATH_SITE . '/templates/' . $templateName . '/app';
            if (array_key_exists('cssJsSources', $result)) {
                $cacheFile = $app . '/cache.json';
                $cache = new Cache($cacheFile);
                $cache->refresh($result['cssJsSources']);
                $cache->save();
            }

            if (array_key_exists('md5Hashes', $result)) {
                $hashesFile = $app . '/hashes.json';
                $haches = new Hash($hashesFile);
                $haches->refresh($result['md5Hashes']);
                $haches->save();
            }

            // update block orders
            if (array_key_exists('positions', $result)) {
                $updater = new ModulesUpdater();
                $updater->update($result['positions']['current']);
            }

            $themeBuilder = new ThemeBuilder($templateName, $media);

            if (array_key_exists('themeFso', $result)) {
                $storage = Helper::buildThemeStorage($result['themeFso']);
                $themeBuilder->export($storage);
            }

            if ('saveProject' === $data['action']) {
                $themeBuilder->updateOriginalTheme();
                //$themeBuilder->buildManifest();
            }

            if (array_key_exists('projectData', $result))
                Project::saveProperty('projectdata', $result['projectData']);

            if (array_key_exists('revision', $result))
                Project::saveProperty('revision', $result['revision']);

            return $this->_response('done');
        } else {
            return $this->_response('processed');
        }    
    }
    
    public function clearChunks($data)
    {
        $chunk = new Chunk();
        $uploadPath = $chunk->UPLOAD_PATH;
        if (($id = $data['id']) && $id && is_dir($uploadPath . $id)) {
            Helper::removeDir($uploadPath . $id);
            return $this->_response('ok');
        } else {
            return $this->_response('fail');
        }    
    }
    
    public function updatePreview($data)
    {
        return $this->_response('updated');
    }
    
    public function setParameters($data)
    {
        $id = isset($data['templateId']) && is_string($data['templateId'])
                && ctype_digit($data['templateId']) ? intval($data['templateId'], 10) : -1;
        if (-1 !== $id)
            $this->_setPatameters($id, $data['params']);
        return $this->_response('parameters setted');
    }
    
    public function renameTheme($data)
    {
        $templateId = $data['templateId'];
        $oldThemeName = $data['oldThemeName'];
        $newThemeName = $data['newThemeName'];
        $oldThemeDir = JPATH_SITE . '/templates/' . $oldThemeName;
        $newThemeDir = JPATH_SITE . '/templates/' . $newThemeName;

        Helper::moveDir($oldThemeDir, $newThemeDir);
        // manifest correction
        $manifest = $newThemeDir . '/templateDetails.xml';
        $data = file_get_contents($manifest);
        $xml = simplexml_load_string($data);
        $xml->name = $newThemeName;
        $path = $xml->config->fields['addfieldpath'];
        $xml->config->fields['addfieldpath'] = str_replace($oldThemeName, $newThemeName, $path);
        $language = $xml->languages->language;
        $xml->languages->language = str_replace($oldThemeName, $newThemeName, $language);
        $dom = new DOMDocument('1.0', 'utf-8');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        $dom->loadXML($xml->asXML());
        $data = $dom->saveXML();
        file_put_contents($manifest, $data);
        // translation file correction
        rename($newThemeDir . '/language/en-GB/en-GB.tpl_' . $oldThemeName . '.ini',
            $newThemeDir . '/language/en-GB/en-GB.tpl_' . $newThemeName . '.ini');

        $this->_rename($templateId, $oldThemeName, $newThemeName);

        return $this->_response('renamed');
    }
    
    private function _rename($id, $oldName, $newName)
    {
        $db = JFactory::getDBO();

        $query = $db->getQuery(true);
        $query->select('title');
        $query->from('#__template_styles');
        $query->where('id=' . $id);
        $db->setQuery($query);
        $title = $db->loadResult();

        $query = $db->getQuery(true);
        $query->update('#__template_styles');
        $query->set('template=' . $db->quote($newName));
        $query->set('title=' . $db->quote(str_replace($oldName, $newName, $title)));
        $query->where('id=' . $id);
        $db->setQuery($query);
        $db->query();

        $query = $db->getQuery(true);
        $query->select('manifest_cache');
        $query->from('#__extensions');
        $query->where('type=' . $db->quote('template')  . ' and element=' . $db->quote($oldName));
        $db->setQuery($query);
        $manifest_cache = $db->loadResult();

        $query = $db->getQuery(true);
        $query->update('#__extensions');
        $query->set('name=' . $db->quote($newName));
        $query->set('element=' . $db->quote($newName));
        $query->set('manifest_cache=' . $db->quote(str_replace($oldName, $newName, $manifest_cache)));
        $query->where('type=' . $db->quote('template')  . ' and element=' . $db->quote($oldName));
        $db->setQuery($query);
        $db->query();

    }
    
    public function getTheme($data)
    {
        $userThemeName  = $data['themeName'];
        $templateName = $data['template'];
        $resultType = $data['resultType'];

        $originalDir = JPATH_SITE . '/templates/' . $templateName;

        $zipFilesArray = array();
        $flags = FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS;
        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($originalDir, $flags));
        foreach ($iterator as $fileInfo) {
            if (preg_match('/^(tmp|editor)/', $iterator->getSubPathname()))
                continue;
            $name = $iterator->getSubPathname();
            $data = file_get_contents($fileInfo->getPathName());
            if ('language/en-GB/en-GB.tpl_' . $templateName . '.ini' === $iterator->getSubPathname()) {
                $name = 'language/en-GB/en-GB.tpl_' . $userThemeName . '.ini';
            }
            if ('templateDetails.xml' === $iterator->getSubPathname()) {
                $xml = simplexml_load_string($data);
                $xml->name = $userThemeName;
                $path = $xml->config->fields['addfieldpath'];
                $xml->config->fields['addfieldpath'] = str_replace($templateName, $userThemeName, $path);
                $language = $xml->languages->language;
                $xml->languages->language = str_replace($templateName, $userThemeName, $language);
                $dom = new DOMDocument('1.0', 'utf-8');
                $dom->preserveWhiteSpace = false;
                $dom->formatOutput = true;
                $dom->loadXML($xml->asXML());
                $data = $dom->saveXML();
            }
            $zipFilesArray[] = array('name' => $name, 'data' => $data);
        }

        jimport( 'joomla.filesystem.archive' );
        $archiveName = $userThemeName . '.zip';
        $zip = JArchive::getAdapter('zip');
        $tmp = $originalDir . '/tmp';
        Helper::createDir($tmp);
        $zip->create($tmp . '/' . $archiveName, $zipFilesArray);
        if ('url' === $resultType) {
            $file = $tmp . '/' . $archiveName;
            if (file_exists($file)) {
                header('Content-Description: File Transfer');
                header('Content-Type: application/octet-stream');
                header('Content-Disposition: attachment; filename='.basename($file));
                header('Content-Transfer-Encoding: binary');
                header('Expires: 0');
                header('Cache-Control: must-revalidate');
                header('Pragma: public');
                header('Content-Length: ' . filesize($file));
                ob_clean(); flush();
                readfile($file);
            }
        } else {
            $ret = base64_encode(file_get_contents($tmp . '/' . $archiveName));
            return $this->_response(array('ext' => 'zip', 'content' => $ret));
        }
    }
    
    public function makeThemeAsActive($data)
    {
        // Include dependancies
        jimport('joomla.application.component.controller');
        // Declaration contstants
        define('JPATH_COMPONENT', JPATH_BASE . '/components/com_templates');
        define('JPATH_COMPONENT_SITE', JPATH_SITE . '/components/com_templates');
        define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/com_templates');
        // Set of variables for controller
        JRequest::setVar('task', 'styles.setDefault');
        JRequest::setVar('cid', $data['templateId']);
        JRequest::setVar(JSession::getFormToken(), '1');
        // Theme activation
        $controller = JController::getInstance('Templates', array('base_path' => JPATH_COMPONENT));
        $controller->execute(JRequest::getCmd('task'));
        return $this->_response('activated');
    }
    
    private function _getTemplateId()
    {
        // determine default template
        $db = JFactory::getDBO();
        $parts = pathinfo(dirname(dirname(__FILE__)));
        $where = array('template = \'' . $parts['filename'] . '\'', 'client_id = 0');
        $query = 'SELECT * FROM #__' . 'template_styles'
            . (count($where) ? ' WHERE ' . implode(' AND ', $where) : '');
        $db->setQuery($query);
        $row = $db->loadRow();
        return $row[0];
    }

    private function _setPatameters($themeId, $params)
    {
        $db = JFactory::getDBO();
        $query = $db->getQuery(true);
        $query->select('params')->from('#__template_styles')->where('id=' . $query->escape($themeId));
        $db->setQuery($query);
        $parameters = $this->_stringToParams($db->loadResult());

        foreach ($params as $key => $value)
            $parameters[$key] = $value;

        $query = $db->getQuery(true);
        $query->update('#__template_styles')->set(
            $db->quoteName('params') . '=' .
                $db->quote($this->_paramsToString($parameters))
        )->where('id=' . $query->escape($themeId));

        $db->setQuery($query);
        $db->query();
    }

    private function _paramsToString($params)
    {
        $registry = new JRegistry();
        $registry->loadArray($params);
        return $registry->toString();
    }

    private function _stringToParams($string)
    {
        $registry = new JRegistry();
        $registry->loadString($string);
        return $registry->toArray();
    }
    
    private function _response($result)
    {
        if (is_string($result)) {
            $result = array('result' => $result);
        }
        return json_encode($result);
    }
    
    public function __call($name, $args)
    {
        exit('Method $Object->' . $name . ' is not exists');
    }
    
}