<?php
/**
 * Created by PhpStorm.
 * User: alex
 * Date: 7/18/18
 * Time: 10:48 AM
 */

class Brizy_Admin_Blocks_Api extends Brizy_Admin_AbstractApi
{

    const nonce = 'brizy-api';

    const GET_SAVED_BLOCK_ACTION = '-get-saved-block';
    const GET_GLOBAL_BLOCKS_ACTION = '-get-global-blocks';
    const GET_SAVED_BLOCKS_ACTION = '-get-saved-blocks';
    const CREATE_GLOBAL_BLOCK_ACTION = '-create-global-block';
    const CREATE_SAVED_BLOCK_ACTION = '-create-saved-block';
    const UPDATE_GLOBAL_BLOCK_ACTION = '-update-global-block';
    const UPDATE_GLOBAL_BLOCKS_ACTION = '-update-global-blocks';
    const UPDATE_SAVED_BLOCK_ACTION = '-saved-global-block';
    const DELETE_GLOBAL_BLOCK_ACTION = '-delete-global-block';
    const DELETE_SAVED_BLOCK_ACTION = '-delete-saved-block';
    const UPDATE_POSITIONS_ACTION = '-update-block-positions';
    const DOWNLOAD_BLOCKS = '-download-blocks';
    const UPLOAD_BLOCKS = '-upload-blocks';

    /**
     * @var Brizy_Admin_Rules_Manager
     */
    private $ruleManager;

    /**
     * @return Brizy_Admin_Blocks_Api
     */
    public static function _init()
    {
        static $instance;
        if (!$instance) {
            $instance = new self(new Brizy_Admin_Rules_Manager());
        }

        return $instance;
    }

    /**
     * Brizy_Admin_Blocks_Api constructor.
     *
     * @param Brizy_Admin_Rules_Manager $ruleManager
     */
    public function __construct($ruleManager)
    {
        $this->ruleManager = $ruleManager;
        parent::__construct();
    }

    protected function getRequestNonce()
    {
        return $this->param('hash');
    }

    /**
     * Saving a page also saves the global blocks it contains, so this path cannot require
     * edit_pages without locking out roles that may edit posts but not pages (ex: contributor).
     * CAP_EDIT_WHOLE_PAGE is togglable per role in Brizy settings and excludes content-only editors.
     *
     * @return void
     */
    private function verifyGlobalBlockWriteAccess()
    {
        if (!current_user_can(Brizy_Admin_Capabilities::CAP_EDIT_WHOLE_PAGE)) {
            $this->error(403, 'Unauthorized.');
        }
    }

    protected function initializeApiActions()
    {
        $pref = 'wp_ajax_' . Brizy_Editor::prefix();
        add_action($pref . self::DOWNLOAD_BLOCKS, array($this, 'actionDownloadBlocks'));
        add_action($pref . self::UPLOAD_BLOCKS, array($this, 'actionUploadBlocks'));
        add_action($pref . self::GET_GLOBAL_BLOCKS_ACTION, array($this, 'actionGetGlobalBlocks'));
        add_action($pref . self::CREATE_GLOBAL_BLOCK_ACTION, array($this, 'actionCreateGlobalBlock'));
        add_action($pref . self::UPDATE_GLOBAL_BLOCK_ACTION, array($this, 'actionUpdateGlobalBlock'));
        add_action($pref . self::UPDATE_GLOBAL_BLOCKS_ACTION, array($this, 'actionUpdateGlobalBlocks'));
        add_action($pref . self::DELETE_GLOBAL_BLOCK_ACTION, array($this, 'actionDeleteGlobalBlock'));
        add_action($pref . self::GET_SAVED_BLOCKS_ACTION, array($this, 'actionGetSavedBlocks'));
        add_action($pref . self::GET_SAVED_BLOCK_ACTION, array($this, 'actionGetSavedBlockByUid'));
        add_action($pref . self::UPDATE_SAVED_BLOCK_ACTION, array($this, 'actionUpdateSavedBlock'));
        add_action($pref . self::CREATE_SAVED_BLOCK_ACTION, array($this, 'actionCreateSavedBlock'));
        add_action($pref . self::DELETE_SAVED_BLOCK_ACTION, array($this, 'actionDeleteSavedBlock'));
        add_action($pref . self::UPDATE_POSITIONS_ACTION, array($this, 'actionUpdateBlockPositions'));
    }

    public function actionDownloadBlocks()
    {
        $this->verifyAuthorization(self::nonce);
        if (!$this->param('uid')) {
            $this->error(400, 'Invalid block uid param');
        }
        try {
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $uids = [];
            // this is not a very eficien solution if you have a big array of uids
            $explode = explode(',', $this->param('uid'));
            $items = array_map(function ($auid) use ($uids, $bockManager) {
                list($uid, $isPro) = explode(':', $auid);
                $uids[] = $uid;
                $item = new Brizy_Editor_Zip_ArchiveItem($uid, $isPro);
                if ($post = $bockManager->getEntity($uid)) {
                    $item->setPost($post);

                    return $item;
                }

                return null;
            }, $explode);
            $items = array_filter($items);
            if (count($items) == 0) {
                $this->error(404, __('There are no blocks to be archived', 'brizy'));
            }
            $fontManager = new Brizy_Admin_Fonts_Manager();
            $zip = new Brizy_Editor_Zip_Archiver(Brizy_Editor_Project::get(), $fontManager, BRIZY_SYNC_VERSION);
            switch ($this->param('type')) {
                case 'popup':
                    $zipPath = "Popup-" . date(DATE_ATOM) . ".zip";
                    break;
                default:
                    $zipPath = "Block-" . date(DATE_ATOM) . ".zip";
                    break;
            }
            $zipPath = $zip->createZip($items, $zipPath);
            header("Pragma: public");
            header("Expires: 0");
            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            header("Cache-Control: private", false);
            header("Content-Type: application/octet-stream");
            header("Content-Disposition: attachment; filename=\"" . basename($zipPath) . "\";");
            header("Content-Transfer-Encoding: binary");
            echo file_get_contents($zipPath);
            exit;
        } catch (Exception $exception) {
            $this->error(400, __($exception->getMessage(), 'brizy'));
        }
    }

    public function actionUploadBlocks()
    {
        try {
            $this->verifyAuthorization(self::nonce);
            if (!isset($_FILES['files'])) {
                $this->error(400, __('Invalid block file'));
            }
            $fields = $this->param('fields') ? $this->param('fields') : [];
            if (!function_exists('wp_handle_upload')) {
                require_once(ABSPATH . 'wp-admin/includes/file.php');
            }
            $file = [
                'name' => $_FILES['files']['name'][0],
                'type' => $_FILES['files']['type'][0],
                'tmp_name' => $_FILES['files']['tmp_name'][0],
                'error' => $_FILES['files']['error'][0],
                'size' => $_FILES['files']['size'][0],
            ];
            $uploadedFile = wp_handle_upload($file, ['test_form' => false]);
            if (isset($uploadedFile['file'])) {
                $zip = new Brizy_Editor_Zip_Archiver(Brizy_Editor_Project::get(), new Brizy_Admin_Fonts_Manager(), BRIZY_SYNC_VERSION);
                list($instances, $errors) = $zip->createFromZip($uploadedFile['file']);
                unset($uploadedFile['file']);
                $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
                $this->success([
                    'success' => $bockManager->createResponseForEntities($instances, $fields),
                    'errors' => $errors,
                ]);
            } else {
                if (isset($uploadedFile['error'])) {
                    $this->error(400, $uploadedFile['error']);
                } else {
                    $this->error(400, __("Invalid zip file provided"));
                }
            }

        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionGetGlobalBlocks()
    {
        $this->verifyAuthorization(self::nonce);
        try {
            $fields = $this->param('fields') ? $this->param('fields') : [];
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL);
            $blocks = $bockManager->getEntities([
                'post_status' => 'any',
                'order' => $this->param('order') ?: 'DESC',
                'orderby' => $this->param('orderby') ?: 'ID'
            ]);
            $this->success($bockManager->createResponseForEntities($blocks, $fields));
        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionCreateGlobalBlock()
    {
        $this->verifyAuthorization(self::nonce);
        if (!$this->param('uid')) {
            $this->error(400, 'Invalid uid');
        }
        if (!$this->param('data')) {
            $this->error(400, 'Invalid data');
        }
        if (!$this->param('meta')) {
            $this->error(400, 'Invalid meta data');
        }
        try {
            $compiledData = stripslashes($this->param('compiled'));
            $editorData = $this->sanitizeJson(stripslashes($this->param('data')));
            $position = stripslashes($this->param('position'));
            $status = stripslashes($this->param('status'));
            $rulesData = stripslashes($this->param('rules'));
            $dependencies = stripslashes($this->param('dependencies'));
            if (!in_array($status, ['publish', 'draft'])) {
                $this->error(400, "Invalid status");
            }
            if (json_decode($editorData) === null && json_last_error() !== JSON_ERROR_NONE) {
                $this->error(400, "Invalid JSON data");
            }
            if ($status == 'publish' && is_null($compiledData)) {
                $this->error(400, "The compiled data is missing");
            }
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL);
            /**
             * @var Brizy_Editor_Block $block ;
             */
            $block = $bockManager->createEntity($this->param('uid'), $status);
            $block->setMeta(stripslashes($this->param('meta')));
            $block->setEditorData($editorData);
            $block->set_needs_compile(true);

            if (is_array($dependencies) && count($dependencies) > 0) {
                $block->setDependencies($dependencies);
            }
            if ($status == 'publish' && $compiledData) {

                $compiled = json_decode($compiledData, true);
                if (is_null($compiled)) {
                    $this->error(400, "The compiled data is invalid");
                }
                $section_manager = $block->getCompiledSectionManager();
                $section_manager->merge(json_decode($compiledData, true));
                $block->setCompiledSections($section_manager->asJson());
                $block->set_compiler_version(BRIZY_EDITOR_VERSION);
            }
            if ($this->param('title')) {
                $block->setTitle(stripslashes($this->param('title')));
            }
            if ($this->param('tags')) {
                $block->setTags(stripslashes($this->param('tags')));
            }
            if ($position) {
                $block->setPosition(Brizy_Editor_BlockPosition::createFromSerializedData(get_object_vars(json_decode($position))));
            }
            // rules
            if ($rulesData) {
                $rules = $this->ruleManager->createRulesFromJson($rulesData, Brizy_Admin_Blocks_Main::CP_GLOBAL);
                $this->ruleManager->addRules($block->getWpPostId(), $rules);
            }
            if (!current_user_can('edit_pages')) {
                $this->error(403, 'Unauthorized.');
            }
            $block->save();
            do_action('brizy_global_block_created', $block);
            $this->success($block->createResponse());

        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionUpdateGlobalBlock()
    {
        $this->verifyAuthorization(self::nonce);
        try {

            if (!$this->param('uid')) {
                $this->error('400', 'Invalid uid');
            }
            $compiledData = stripslashes($this->param('compiled'));
            $status = stripslashes($this->param('status'));
            $dependencies = json_decode(stripslashes($this->param('dependencies')));
            if (!in_array($status, ['publish', 'draft'])) {
                $this->error(400, "Invalid post type");
            }
            if ($status == 'publish' && is_null($compiledData)) {
                $this->error(400, "The compiled data is missing");
            }
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL);
            $block = $bockManager->getEntity($this->param('uid'));
            if (!$block) {
                $this->error(400, "Global block not found");
            }
            // some setters below write straight to post meta, so this must run before them
            $this->verifyGlobalBlockWriteAccess();
            /**
             * @var Brizy_Editor_Block $block ;
             */
            if ($this->param('meta')) {
                $block->setMeta(stripslashes($this->param('meta')));
            }
            if ($this->param('data')) {
                $data = $this->sanitizeJson(stripslashes($this->param('data')));
                if (json_decode($data) !== null && !json_last_error()) {
                    $block->setEditorData($data);
                }
            }

            $compiled_section_manager = $block->getCompiledSectionManager();

            if ($this->param('title')) {
                $block->setTitle(stripslashes($this->param('title')));
            }

            if ($compiledData) {
                $block->set_compiler(Brizy_Editor_Post::COMPILER_EXTERNAL);
                $compiled_sections = json_decode($compiledData, true);
                if (!$compiled_sections) {
                    $this->error(400, "The compiled data is invalid");
                }
                $compiled_section_manager->merge($compiled_sections);
                $block->setCompiledSections($compiled_section_manager->asJson());
                $block->setHtml('');
            }

            if ($this->param('tags')) {
                $block->setTags(stripslashes($this->param('tags')));
            }
            if (is_array($dependencies)) {
                $block->setDependencies($dependencies);
            }
            if ((int)$this->param('is_autosave')) {
                $block->save(1);
            } else {
                // issue: #14271
                //$block->setDataVersion( $this->param( 'dataVersion' ) );
                $block->getWpPost()->post_status = $status;
                // position
                $position = stripslashes($this->param('position'));
                if ($position) {
                    $block->setPosition(Brizy_Editor_BlockPosition::createFromSerializedData(get_object_vars(json_decode($position))));
                }
                // rules
                $rulesData = stripslashes($this->param('rules'));
                if ($rulesData) {
                    $rules = $this->ruleManager->createRulesFromJson($rulesData, Brizy_Admin_Blocks_Main::CP_GLOBAL);
                    $this->ruleManager->setRules($block->getWpPostId(), $rules);
                }
                $block->save(0);
                do_action('brizy_global_block_updated', $block);
            }
            Brizy_Editor_Block::cleanClassCache();
            $this->success(Brizy_Editor_Block::get($block->getWpPostId())->createResponse());
        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionUpdateGlobalBlocks()
    {
        $this->verifyAuthorization(self::nonce);
        try {

            $this->verifyGlobalBlockWriteAccess();
            if (!$this->param('uid')) {
                $this->success([]);
            }
            foreach ((array)$this->param('uid') as $i => $uid) {

                if (!$this->param('uid')[$i]) {
                    $this->error('400', 'Invalid uid');
                }
                $status = stripslashes($this->param('status')[$i]);
                if (!in_array($status, ['publish', 'draft'])) {
                    $this->error(400, "Invalid post type");
                }
            }
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL);
            $blocks = $bockManager->getEntity((array)$this->param('uid'));
            foreach ((array)$this->param('uid') as $i => $uid) {

                if (!isset($blocks[$uid])) {
                    $this->error(400, "Global block not found");
                }
                /**
                 * @var Brizy_Editor_Block $block ;
                 */
                $status = stripslashes($this->param('status')[$i]);
                $block = $blocks[$uid];
                if (isset($this->param('meta')[$i])) {
                    $block->setMeta(stripslashes($this->param('meta')[$i]));
                }
                $compiled_section_manager = $block->getCompiledSectionManager();
                if (isset($this->param('compiled')[$i])) {
                    $compiled_sections = stripslashes($this->param('compiled')[$i]);
                    $compiled_sections = json_decode($compiled_sections, true);
                    if (!$compiled_sections) {
                        $this->error(400, "The compiled data is invalid");
                    }
                    $compiled_section_manager->merge($compiled_sections);
                    $block->setCompiledSections($compiled_section_manager->asJson());
                    $block->set_compiler_version(BRIZY_EDITOR_VERSION);
                    $block->set_needs_compile(false);
                    $block->set_compiler(Brizy_Editor_Entity::COMPILER_BROWSER);
                }
                if (isset($this->param('title')[$i])) {
                    $block->setTitle(stripslashes($this->param('title')[$i]));
                }
                if (is_array($this->param('dependencies')[$i]) && count($this->param('dependencies')[$i]) > 0) {
                    $block->setDependencies($this->param('dependencies')[$i]);
                }
                if (isset($this->param('tags')[$i])) {
                    $block->setTags(stripslashes($this->param('tags')[$i]));
                }
                if (isset($this->param('data')[$i]) && !empty($this->param('data')[$i])) {
                    $data = $this->sanitizeJson(stripslashes($this->param('data')[$i]));
                    if (json_decode($data) !== null && !json_last_error()) {
                        $block->setEditorData($data);
                    }
                }

                if (isset($this->param('is_autosave')[$i]) && (int)$this->param('is_autosave')[$i] === 1) {
                    $block->save(1);
                } else {

                    // issue: #14271
                    //$block->setDataVersion( $this->param( 'dataVersion' )[ $i ] );
                    $block->getWpPost()->post_status = $status;
                    // position
                    $position = stripslashes($this->param('position')[$i]);
                    if ($position && ($positionObject = json_decode($position))) {
                        $block->setPosition(Brizy_Editor_BlockPosition::createFromSerializedData(get_object_vars($positionObject)));
                    }
                    // rules
                    $rulesData = stripslashes($this->param('rules')[$i]);
                    if ($rulesData) {
                        $rules = $this->ruleManager->createRulesFromJson($rulesData, Brizy_Admin_Blocks_Main::CP_GLOBAL);
                        $this->ruleManager->setRules($block->getWpPostId(), $rules);
                    }
                    $block->save();
                    do_action('brizy_global_block_updated', $block);
                }
            }
            $this->success([]);

        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionDeleteGlobalBlock()
    {
        $this->verifyAuthorization(self::nonce);
        if (!current_user_can('edit_pages')) {
            $this->error(403, 'Unauthorized.');
        }
        if (!$this->param('uid')) {
            $this->error('400', 'Invalid uid');
        }
        $block = $this->getBlock($this->param('uid'), Brizy_Admin_Blocks_Main::CP_GLOBAL);
        if ($block) {
            do_action('brizy_global_block_deleted', $block);
            do_action('brizy_global_data_deleted');
            $this->deleteBlock($block, Brizy_Admin_Blocks_Main::CP_GLOBAL);
            $this->success(null);
        }
        $this->error('404', 'Block not found');
    }

    public function actionGetSavedBlocks()
    {
        $this->verifyAuthorization(self::nonce);
        try {
            $fields = $this->param('fields') ? $this->param('fields') : [];
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $blocks = $bockManager->getEntities([
                'paged' => (int)($this->param('page') ?: 1),
                'posts_per_page' => (int)($this->param('count') ?: -1),
                'order' => $this->param('order') ?: 'ASC',
                'orderby' => $this->param('orderby') ?: 'ID',
            ]);
            $blocks = apply_filters('brizy_get_saved_blocks', $bockManager->createResponseForEntities($blocks, $fields), $fields, $bockManager);
            $this->success($blocks);
        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionGetSavedBlockByUid()
    {
        $this->verifyAuthorization(self::nonce);
        if (!$this->param('uid')) {
            $this->error(400, 'Invalid uid');
        }
        $fields = $this->param('fields') ? $this->param('fields') : [];
        try {

            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $block = $bockManager->getEntity($this->param('uid'));
            $block = apply_filters('brizy_get_saved_block', $block, $this->param('uid'), $bockManager);
            if (!$block) {
                $this->error(404, 'Block not found');
            }
            $this->success($block->createResponse($fields));
        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionCreateSavedBlock()
    {
        $this->verifyAuthorization(self::nonce);
        if (!current_user_can('edit_pages')) {
            $this->error(403, 'Unauthorized.');
        }
        if (!$this->param('uid')) {
            $this->error(400, 'Invalid uid');
        }
        if (!$this->param('data')) {
            $this->error(400, 'Invalid data');
        }
        if (!$this->param('meta')) {
            $this->error(400, 'Invalid meta data');
        }
        if (!$this->param('media')) {
            $this->error(400, 'Invalid media data provided');
        }
        try {
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $block = $bockManager->createEntity($this->param('uid'));
            $block->setMedia(stripslashes($this->param('media')));
            $block->setMeta(stripslashes($this->param('meta')));
            if ($this->param('title')) {
                $block->setTitle(stripslashes($this->param('title')));
            }
            if ($this->param('tags')) {
                $block->setTags(stripslashes($this->param('tags')));
            }
            $block->setEditorData($this->sanitizeJson(stripslashes($this->param('data'))));
            $block->set_needs_compile(true);
            //$block->setCloudUpdateRequired( true );
            $block->save();
            do_action('brizy_saved_block_created', $block);
            $this->success($block->createResponse());

        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionUpdateSavedBlock()
    {
        $this->verifyAuthorization(self::nonce);
        if (!current_user_can('edit_pages')) {
            $this->error(403, 'Unauthorized.');
        }
        try {
            if (!$this->param('uid')) {
                $this->error('400', 'Invalid uid');
            }
            if ($this->param('dataVersion') === null) {
                $this->error('400', 'Invalid data version');
            }
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $block = $bockManager->getEntity($this->param('uid'));
            if (!$block instanceof Brizy_Editor_Block) {
                $this->error('404', 'Block not found');
            }
            $block->setDataVersion($this->param('dataVersion'));
            if ($this->param('data')) {
                $block->setEditorData($this->sanitizeJson(stripslashes($this->param('data'))));
            }
            if ($this->param('media')) {
                $block->setMedia(stripslashes($this->param('media')));
            }
            if ($this->param('meta')) {
                $block->setMeta(stripslashes($this->param('meta')));
            }
            if ($this->param('title')) {
                $block->setTitle(stripslashes($this->param('title')));
            }
            if ($this->param('tags')) {
                $block->setTags(stripslashes($this->param('tags')));
            }
            if ((int)$this->param('is_autosave')) {
                $block->save(1);
            } else {
                $block->save();
                do_action('brizy_saved_block_updated', $block);
            }
            Brizy_Editor_Block::cleanClassCache();
            $this->success(Brizy_Editor_Block::get($block->getWpPostId())->createResponse());
        } catch (Exception $exception) {
            $this->error(400, $exception->getMessage());
        }
    }

    public function actionDeleteSavedBlock()
    {
        $this->verifyAuthorization(self::nonce);
        if (!current_user_can('edit_pages')) {
            $this->error(403, 'Unauthorized.');
        }
        if (!$this->param('uid')) {
            $this->error('400', 'Invalid uid');
        }
        try {
            $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_SAVED);
            $block = $bockManager->getEntity($this->param('uid'));
            do_action('brizy_saved_block_delete', $this->param('uid'));
            if ($block) {
                do_action('brizy_global_data_deleted');
                $bockManager->deleteEntity($block);
            } else {
                $this->error('404', 'Block not found');
            }
        } catch (Exception $e) {
            $this->error('500', 'Unable to delete block');
        }
        $this->success(null);
    }

    public function actionUpdateBlockPositions()
    {

        global $wpdb;
        $this->verifyAuthorization(self::nonce);
        $this->verifyGlobalBlockWriteAccess();
        $data = file_get_contents("php://input");
        $dataObject = json_decode($data);
        if (!$dataObject) {
            $this->error(400, 'Invalid position data provided');
        }
        $wpdb->query('START TRANSACTION');
        try {

            foreach (get_object_vars($dataObject) as $uid => $position) {

                if (!(isset($position->top) && isset($position->bottom) && isset($position->align))) {
                    throw  new Exception();
                }
                $positionObj = new Brizy_Editor_BlockPosition($position->top, $position->bottom, $position->align);
                $bockManager = new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL);
                $block = $bockManager->getEntity($uid);
                if (!$block) {
                    throw  new Exception();
                }
                $block->setPosition($positionObj);
                if ($this->param('is_autosave') == 1) {
                    $block->save(1);
                } else {
                    $block->saveStorage();
                }
                do_action('brizy_global_block_updated', $block);
            }
            $wpdb->query('COMMIT');

        } catch (Exception $e) {
            $wpdb->query('ROLLBACK');
            $this->error('400', 'Unable to save block positions');
        }
        $this->success(json_encode($dataObject));
    }


    /**
     * @param $uid
     * @param $postType
     *
     * @return string|null
     */
    private function getBlockIdByUidAndBlockType($uid, $postType)
    {
        global $wpdb;
        $prepare = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} p 
								JOIN {$wpdb->postmeta} pm  ON 
								pm.post_id=p.ID and 
								meta_key='brizy_post_uid' and 
								meta_value='%s'   
								WHERE p.post_type IN ('%s')
								ORDER BY p.ID DESC
								LIMIT 1", array($uid, $postType));

        return $wpdb->get_var($prepare);
    }

    /**
     * @param $uid
     * @param $postType
     *
     * @return string|null
     */
    private function getBlockIdByUid($uid)
    {
        global $wpdb;
        $prepare = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} p 
								JOIN {$wpdb->postmeta} pm  ON pm.post_id=p.ID and meta_key='brizy_post_uid' and meta_value='%s'
								WHERE p.post_type <> 'attachment'   
								ORDER BY p.ID DESC
								LIMIT 1", array($uid,));

        return $wpdb->get_var($prepare);
    }

    /**
     * @param $id
     * @param $postType
     *
     * @return Brizy_Editor_Block|null
     * @throws Brizy_Editor_Exceptions_NotFound
     */
    private function getBlock($id, $postType)
    {
        $postId = $this->getBlockIdByUidAndBlockType($id, $postType);
        if ($postId) {
            return Brizy_Editor_Block::get($postId);
        }

        return null;
    }

    /**
     * @param $uid
     * @param $status
     * @param $type
     *
     * @return Brizy_Editor_Block
     * @throws Brizy_Editor_Exceptions_NotFound
     */
    private function createBlock($uid, $status, $type)
    {
        $name = md5(time());
        $post = wp_insert_post(array(
            'post_title' => '',
            'post_name' => $name,
            'post_status' => $status,
            'post_type' => $type,
        ));
        if ($post) {
            $brizyPost = Brizy_Editor_Block::get($post, $uid);
            $brizyPost->set_uses_editor(true);
            $brizyPost->set_needs_compile(true);
            $brizyPost->setDataVersion(1);

            return $brizyPost;
        }
        throw new Exception('Unable to create block');
    }

    /**
     * @param $postUid
     * @param $postType
     *
     * @return false|WP_Post|null
     */
    private function deleteBlock($block, $postType)
    {

        if ($postType === Brizy_Admin_Blocks_Main::CP_SAVED) {

        }

        return wp_delete_post($block->getWpPostId());
    }
}
