<?php

include_once 'UpageHelper.php';
include_once 'UpageSectionsManager.php';
include_once 'UpageMappers.php';

class UpagePostManager {
    public function __construct() {}

    /**
     * @param $data
     */
    public function execute($data)
    {
        if ($this->_userAuthorized($data)) {
            echo $this->{$data['action']}($data);
        } else {
            echo "Session error";
        }
    }

    /**
     * @param $data
     * @return bool
     */
    private function _userAuthorized($data)
    {
        // checking user privileges
        $user = JFactory::getUser();
        $session = JFactory::getSession();
        if (!(1 !== (integer)$user->guest && 'active' === $session->getState()))
            return false;
        return true;
    }

    public function duplicatePage()
    {

    }

    public function updatePageSections()
    {
        $result = array();
        // to do
        return $this->_response(array(
            'result' => 'done',
            'data' => $result,
        ));
    }
    public function updatePages($data)
    {
        $result = array(
            'add' => array(),
            'update' => array(),
        );

        $data = $data['data'];
        if (isset($data['add'])) {
            foreach($data['add'] as $add_data) {
                $result['add'][] = $this->_updatePostAdd($add_data);
            }
        }
        if (isset($data['update'])) {
            foreach($data['update'] as $update_data) {
                $result['update'][] = $this->_updatePostUpdate($update_data);
            }
        }
        if (isset($data['remove'])) {
            foreach($data['remove'] as $remove_data) {
                $this->_updatePostRemove($remove_data);
            }
        }

        return $this->_response(array(
            'result' => 'done',
            'data' => $result,
        ));
    }

    private function _updatePostAdd($data)
    {
        $postId = $data['id'];
        $postTitle = $data['title'];
        $contentMapper = Upage_Data_Mappers::get('content');

        $contentList = $contentMapper->find(array('id' => $data['id']));
        $article = null;
        if (count($contentList) > 0) {
            if ($postTitle) {
                $db = JFactory::getDBO();
                $query = $db->getQuery(true);
                $query->update('#__content');
                $query->set($db->quoteName('title') . '="' . $postTitle . '"');
                $query->where('id=' . $contentList[0]->id);
                $db->setQuery($query);
                $db->query();

                $res = $contentMapper->find(array('id' => $contentList[0]->id));
                if (count($res) > 0)
                    $article = $res[0];
            }
        } else {
            $defCatTitle = 'Uncategorised';
            $categoryMapper = Upage_Data_Mappers::get('category');
            $res = $categoryMapper->find(array('title' => $defCatTitle));
            $catId = '';
            if (count($res) > 0) {
                $catId = $res[0]->id;
            } else {
                $categoryObj = $categoryMapper->create();
                $categoryObj->title = $defCatTitle;
                $categoryObj->extension = 'com_content';
                $categoryObj->metadata = $this->_paramsToString(array('robots' => '', 'author' => '', 'tags' => ''));
                $status = $categoryMapper->save($categoryObj);
                if (is_string($status))
                    trigger_error($status, E_USER_ERROR);
                $catId = $categoryObj->id;
            }
            $article = $contentMapper->create();
            $article->catid = $catId;
            $article->title = $postTitle ? $postTitle : 'post_' . round(microtime(true));
            $date = new JDate();
            $article->alias = $date->format('Y-m-d-H-i-s');
            $article->introtext = '';
            $article->attribs = $this->_paramsToString(array
            (
                'show_title' => '',
                'link_titles' => '',
                'show_intro' => '',
                'show_category' => '',
                'link_category' => '',
                'show_parent_category' => '',
                'link_parent_category' => '',
                'show_author' => '',
                'link_author' => '',
                'show_create_date' => '',
                'show_modify_date' => '',
                'show_publish_date' => '',
                'show_item_navigation' => '',
                'show_icons' => '',
                'show_print_icon' => '',
                'show_email_icon' => '',
                'show_vote' => '',
                'show_hits' => '',
                'show_noauth' => '',
                'alternative_readmore' => '',
                'article_layout' => ''
            ));
            $article->metadata = $this->_paramsToString(array('robots' => '', 'author' => '', 'rights' => '', 'xreference' => '', 'tags' => ''));
            $status = $contentMapper->save($article);
            if (is_string($status))
                trigger_error($status, E_USER_ERROR);
        }
        return $this->_getPage($article);
    }

    private function _updatePostUpdate($data)
    {
        $this->_updatePostAdd($data);
    }

    private function _updatePostRemove($data)
    {
        $contentMapper = Upage_Data_Mappers::get('content');
        $contentMapper->delete($data['id']);
    }

    /**
     * @param $data
     * @return mixed|string
     */
    public function getPage($data)
    {
        $postId = $data['pageId'];
        $db = JFactory::getDBO();
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__content');
        $query->where('state = 1');
        $query->where('id = ' . $postId);
        $db->setQuery($query);
        $list = $db->loadObjectList();
        $result = array();
        if (count($list) > 0) {
            $result = $this->_getPage($list[0]);
        }
        return $this->_response(array(
            'result' => 'done',
            'data' => $result,
        ));
    }

    /**
     * @return mixed|string
     */
    public function getSite()
    {
        return $this->_response(array(
            'result' => 'done',
            'data' => $this->_buildSiteObject(),
        ));
    }

    /**
     * @return array
     */
    private function _buildSiteObject()
    {
        $site = array(
            'id' => $this->getSiteId(),
            'items' => array(),
            'order' => 0,
            'publicUrl' => '',
            'status' => 2,
            'title' => 'My Site'
        );

        $pages = array();

        $db = JFactory::getDBO();
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__content');
        $query->where('state = 1');
        $query->order('created', 'desc');
        $db->setQuery($query);
        $list = $db->loadObjectList();

        foreach($list as $key => $item)
            $pages[] = $this->_getPage($item);

        $site['items'] = $pages;
        return $site;
    }

    /**
     * @param $postObject
     * @return array
     */
    private function _getPage($postObject)
    {
        $current = dirname(dirname(dirname(dirname(dirname(JURI::current()))))) . '/';
        return array(
            'siteId' => $this->getSiteId(),
            'title' => $postObject->title,
            'publicUrl' =>  $current . 'index.php?option=com_content&view=article&id=' . $postObject->id,
            'items' => $this->_getSections($postObject),
            'canShare' => false,
            'html' => null,
            'keywords' => null,
            'imagesUrl' => array(),
            'id' => $postObject->id,
            'order' =>  0,
            'status' => 2
        );
    }

    /**
     * @param $postObject
     * @return array
     */
    private function _getSections($postObject)
    {
        $content = UpagePostManager::getArticleContent($postObject->id);
        $sections = array();
        if (preg_match_all('/\[upage_section\s*id=(\d+)\s*\]/', $content, $matches, PREG_SET_ORDER)) {
            if (count($matches) > 0) {
                foreach ($matches as $l => $match) {
                    $sectionObject = UpageSectionsManager::getSectionById($match[1]);
                    if ($sectionObject) {
                        $section = array(
                            'id' => $sectionObject->id,
                            'pageId' => $postObject->id,
                            'thumbnailUrl' => $sectionObject->image,
                            'status' => 2,
                            'order' => $l,
                        );
                        if (preg_match('# data-id="([^"]*?)"#', $sectionObject->content, $matches)) {
                            $section['clientId'] = $matches[1];
                        }
                        $sections[] = $section;
                    }
                }
            }
        }
        return $sections;
    }

    /**
     * @return int
     */
    public function getSiteId()
    {
        return 1;
    }

    /**
     * @param $data
     * @return bool|mixed|string
     */
    public function uploadImage($data) {

        jimport('joomla.filesystem.file');

        $params = JComponentHelper::getParams('com_media');
        $imagesDirFromParams = $params->get('file_path', 'images');
        $imagesFolder = JPATH_ROOT . '/' . $imagesDirFromParams;
        $upageContentFolder = JPath::clean(implode('/', array($imagesFolder, 'upage-content')));
        $file = $_FILES['async-upload'];

        $type = exif_imagetype($file['tmp_name']);
        switch($type)
        {
            case IMAGETYPE_GIF:
                $ext = 'gif';
                break;
            case IMAGETYPE_JPEG:
                $ext = 'jpg';
                break;
            case IMAGETYPE_PNG :
                $ext = 'png';
                break;
            case IMAGETYPE_BMP :
                $ext = 'bmp';
                break;
            default:
                $ext = 'jpg';
        }

        do {
            $name = md5(microtime() . rand(0, 9999));
            $file['filepath'] = $upageContentFolder . '/' . $name . '.' . $ext;
        } while (file_exists($file['filepath']));

        $objectFile = new JObject($file);
        if (!JFile::upload($objectFile->tmp_name, $objectFile->filepath))
        {
            // Error in upload
            JError::raiseWarning(100, JText::_('Unable to upload file'));//COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE
            return false;
        }
        $imagesUrl = str_replace(JPATH_ROOT, dirname(dirname(dirname(dirname(dirname(JUri::current()))))), $file['filepath']);
        $imagesUrl = str_replace('\\', '/',$imagesUrl);
        return $this->_response(array(
            'status' => 'done',
            'upload_id' => '',
            'image_url' => $imagesUrl
        ));
    }

    /**
     * @param $data
     * @return array|mixed|string
     */
    public function uploadSections($data)
    {
        if (!isset($data['sections']) || !is_array($data['sections'])) {
            return array(
                'status' => 'error',
                'message' => 'sections parameter missing',
            );
        }

        $result = array();

        $sections = $data['sections'];
        foreach($sections as $section) {
            $html = $section['html'];
            $name = isset($section['name']) ? $section['name'] : 'Section';
            $mediaId = isset($section['mediaId']) ? $section['mediaId'] : 0;
            $thumbnailUrl = isset($section['thumbnail']) && is_array($section['thumbnail']) ? $section['thumbnail']['url'] : '';

            $db = JFactory::getDBO();
            if ($mediaId) {
                // update section
                $query = $db->getQuery(true);
                $query->update('#__upage_sections');
                $query->set($db->quoteName('title') . '=' . $db->quote($name));
                $query->set($db->quoteName('content') . '=' . $db->quote($html));
                $query->set($db->quoteName('image') . '=' . $db->quote($thumbnailUrl));
                $query->where('id=' . $query->escape($mediaId));
                $db->setQuery($query);
                $db->query();
            }  else {
                // add section
                $row = new UpageSectionTable($db);
                $row->title = $name;
                $row->content = $html;
                $row->image = $thumbnailUrl;
                if (!$row->check())
                    return array(
                        'status' => 'error',
                        'message' => $row->getError(),
                    );
                if (!$row->store())
                    return array(
                        'status' => 'error',
                        'message' => $row->getError(),
                    );
                $mediaId = $row->id;
            }
            $result[] = array(
                'section_id' => $mediaId
            );
        }
        return $this->_response(array(
            'result' => 'done',
            'data' => $result,
        ));
    }

    /**
     * @param $data
     * @return array|mixed|string
     */
    public function updatePost($data)
    {
        if (!isset($data['id']) || !isset($data['content'])) {
            return array(
                'status' => 'error',
                'message' => 'post parameter missing',
            );
        }

        $postId = $data['id'];
        $shortcodes = $data['content'];

        $content = UpagePostManager::getArticleContent($postId);
        if (null !== $content) {
            $newContent = $this->_generatePostWithShortcodes($content, $shortcodes);
            UpagePostManager::setArticleContent($newContent, $postId);
        }

        return $this->_response(array(
            'result' => 'done',
        ));
    }

    /**
     * @param $content
     * @param $shortcodes
     * @return string
     */
    private function _generatePostWithShortcodes($content, $shortcodes)
    {
        $old = $this->_splitContentBySection($content);
        $new = $this->_splitContentBySection($shortcodes);
        $new = array_filter($new, create_function('$a', 'return $a["type"] === "section";'));

        $presents_ids = array();
        foreach($new as $part) {
            $presents_ids[$part['id']] = true;
        }

        $blocks = array();
        $last_id = 'start';
        foreach($old as $part) {
            if ($part['type'] !== 'section') {
                $blocks[$last_id][] = $part;
            } if (isset($part['id']) && isset($presents_ids[$part['id']])) {
                $last_id = $part['id'];
                $blocks[$last_id] = array($part);
            }
        }

        $result = '';
        foreach($new as $part) {
            $id = $part['id'];
            if (!isset($blocks[$id])) {
                // it's a new section
                $result .= "[upage_section id=$id]\n";
            } else {
                foreach ($blocks[$id] as $old_part) {
                    if ($old_part['type'] !== 'section') {
                        $result .= $old_part['text'];
                    } else if ($id !== 'start') {
                        $result .= "[upage_section id=$id]";
                    }
                }
            }
        }
        return $result;
    }

    /**
     * @param $content
     * @return array
     */
    private function _splitContentBySection($content)
    {
        require_once JPATH_PLUGINS . '/content/themlercontent/lib/Shortcodes.php';
        ShortcodesUtility::stackPush(array(
            "#^upage_section$#" => 'UpagePostManager::sectionPlaceholder'
        ));
        $content = ShortcodesUtility::doShortcode($content);
        ShortcodesUtility::stackPop();

        $parts = preg_split('#(%SECTION\d*%)#', $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
        $result = array(
            array(
                'type' => 'section',
                'id' => 'start',
            )
        );
        foreach($parts as $part) {
            if (preg_match('#^%SECTION(\d*)%$#', $part, $m)) {
                $result[] = array(
                    'type' => 'section',
                    'id' => $m[1],
                );
            } else {
                $result[] = array(
                    'type' => 'text',
                    'text' => $part,
                );
            }
        }
        return $result;
    }

    /**
     * @param $atts
     * @param string $content
     * @return string
     */
    public static function sectionPlaceholder($atts, $content = '') {
        $atts = ShortcodesUtility::atts(array(
            'id' => ''
        ), $atts);

        $id = $atts['id'];
        return "%SECTION$id%";
    }

    /**
     * @param $id
     * @return null|string
     */
    public static function getArticleContent($id)
    {
        if ('' == $id)
            return '';
        $db = JFactory::getDBO();
        $query = 'SELECT * FROM #__content'
            . ' WHERE id = ' . intval($id)
            . ' ORDER BY id';
        $db->setQuery($query, 0, 0);
        $rows = $db->loadAssocList();
        if ($db->getErrorNum())
            return null;
        if (count($rows) < 1)
            return null;

        $result = JTable::getInstance('content');
        $result->bind($rows[0]);
        return $result->introtext . '[[DELIMITER]]' . $result->fulltext;
    }

    /**
     * @param $content
     * @param $id
     */
    public static function setArticleContent($content, $id)
    {
        if ('' == $id)
            return;
        $parts = explode('[[DELIMITER]]', $content);
        $intro = $parts[0];
        $full = count($parts) > 1 ? $parts[1] : '';

        $db = JFactory::getDBO();
        $query = $db->getQuery(true);
        $query->update('#__content');
        $query->set($db->quoteName('introtext') . '=' . $db->quote($intro));
        $query->set($db->quoteName('fulltext') . '=' . $db->quote($full));
        $query->where('id=' . $query->escape($id));
        $db->setQuery($query);
        $db->query();
    }

    /**
     * @param $result
     * @return mixed|string
     */
    private function _response($result)
    {
        if (is_string($result)) {
            $result = array('result' => $result);
        }
        return json_encode($result);
    }

    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();
    }
}