<?php
namespace MatthiasWeb\RealMediaLibrary\lite\folder;

use Exception;
use MatthiasWeb\RealMediaLibrary\exception\FolderAlreadyExistsException;
use MatthiasWeb\RealMediaLibrary\exception\OnlyInProVersionException;
use MatthiasWeb\RealMediaLibrary\Util;

// phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- This trait throws internal exceptions and returns internal messages.

// @codeCoverageIgnoreStart
defined('ABSPATH') or die('No script kiddies please!'); // Avoid direct file request
// @codeCoverageIgnoreEnd

trait Creatable {
    // Documented in IFolderActions
    public function resetSubfolderOrder() {
        throw new OnlyInProVersionException(__METHOD__);
    }

    // Documented in IFolderActions
    public function orderSubfolders($orderby, $writeMetadata = true) {
        throw new OnlyInProVersionException(__METHOD__);
    }

    // Documented in IFolderActions
    protected function applySubfolderOrderBy() {
        return false;
    }

    // Documented in IOverrideCreatable
    public function persistCheckParent() {
        // The Lite version can currently not handle hierarchical folders
        if ($this->parent > -1) {
            throw new OnlyInProVersionException(__METHOD__);
        }
    }

    // Documented in IFolderActions
    public function reindexChildrens($resetData = false) {
        return false;
    }

    // Documented in IFolder
    public function isValidChildrenType($type) {
        // In Lite version we can only have subfolders in Unorganized, so allow all folder types
        return true;
    }

    // Documented in IFolderActions
    public function setParent($id, $ord = -1, $force = false) {
        // Always root as the Lite version does not support subfolders
        $rootFolderId = _wp_rml_root();
        $rootFolder = wp_rml_get_object_by_id($rootFolderId);

        $this->debug("Try to set parent of $this->id from $this->parent to $rootFolderId...", __METHOD__);

        // Get the parent object
        if ($rootFolderId === $this->parent) {
            $this->debug('The parent is the same, probably only the order is changed...', __METHOD__);
        } elseif ($rootFolder->hasChildren($this->name)) {
            // For backwards compatibility (4.12.0) we need to do this checks in Lite version, too
            // Check, if the parent has already the given folder name
            throw new FolderAlreadyExistsException($rootFolderId, $this->name);
        }

        $newOrder = $ord > -1 ? $ord : $rootFolder->getMaxOrder() + 1;
        $isRelocate = $rootFolderId === $this->parent;

        /**
         * This action is called when a folder was relocated in the folder tree. That
         * means the parent was not changed, only the order was changed.
         *
         * @param {IFolder} $folder The folder object
         * @param {int} $id The new parent folder id
         * @param {int} $order The (new) order number
         * @param {boolean} $force If true the relocating was forced
         * @hook RML/Folder/Relocate
         * @since 4.0.7
         */

        // For backwards compatibility (4.12.0) we need the other action, too
        do_action($isRelocate ? 'RML/Folder/Relocate' : 'RML/Folder/Move', $this, $rootFolderId, $newOrder, $force);

        $oldData = $this->getRowData();
        $beforeId = $this->parent;
        $this->parent = $rootFolderId;
        $this->order = $newOrder;
        $this->debug("Use $this->order (passed $ord as parameter) as new order value", __METHOD__);

        // Save in database
        if ($this->id > -1) {
            global $wpdb;

            // Update childrens absolute pathes (backwards compatible 4.12.0)
            if ($beforeId !== $this->parent) {
                $this->updateThisAndChildrensAbsolutePath();
            }

            // Update order
            // phpcs:disable WordPress.DB.PreparedSQL
            $table_name = $this->getTableName();
            $wpdb->query(
                $wpdb->prepare(
                    "UPDATE $table_name SET parent=%d, ord=%d WHERE id = %d",
                    $rootFolderId,
                    $this->order,
                    $this->id
                )
            );
            // phpcs:enable WordPress.DB.PreparedSQL

            /**
             * This action is called when a folder was relocated in the folder tree. That
             * means the parent was not changed, only the order was changed.
             *
             * @param {IFolder} $folder The folder object
             * @param {int} $id The new parent folder id
             * @param {int} $order The (new) order number
             * @param {boolean} $force If true the relocating was forced
             * @param {object} $oldData The old SQL row data (raw) of the folder
             * @hook RML/Folder/Relocated
             */

            // For backwards compatibility (4.12.0) we need the other action, too
            do_action(
                $isRelocate ? 'RML/Folder/Relocated' : 'RML/Folder/Moved',
                $this,
                $rootFolderId,
                $this->order,
                $force,
                $oldData
            );
            $this->debug('Successfully moved and saved in database', __METHOD__);

            Util::getInstance()->doActionAnyParentHas($this, 'Folder/RelocatedOrMoved', [
                $this,
                $rootFolderId,
                $this->order,
                $force,
                $oldData,
            ]);
        } else {
            $this->debug('Successfully setted the new parent', __METHOD__);
            $this->getAbsolutePath(true, true);
        }

        return true;
    }

    // Documented in IFolderActions
    public function relocate($parentId, $nextFolderId = false) {
        global $wpdb;

        // Always root as the Lite version does not support subfolders
        $rootFolderId = _wp_rml_root();

        // Collect data
        $table_name = $this->getTableName();
        $this->debug(
            $nextFolderId === false
                ? 'The folder should take place at the end of the list...'
                : "The folder should take place before folder id $nextFolderId...",
            __METHOD__
        );
        $rootFolder = $rootFolderId === $this->id ? $this : wp_rml_get_object_by_id($rootFolderId);
        $next = $nextFolderId === false ? null : wp_rml_get_object_by_id($nextFolderId);

        // At end of the list
        try {
            if ($next === null && is_rml_folder($rootFolderId)) {
                // Only update the order to the end of the list
                $this->setParent(null);
            } elseif (is_rml_folder($next) && is_rml_folder($rootFolder)) {
                // Reget
                $_this = wp_rml_structure_reset(null, false, $this->id);
                $next = wp_rml_get_object_by_id($next->id);

                // Get the order of the next folder
                $newOrder = $next->order;

                // Count up the next ids
                // phpcs:disable WordPress.DB.PreparedSQL
                $sql = "UPDATE $table_name SET ord = ord + 1 WHERE parent = $rootFolderId AND ord >= $newOrder";
                $wpdb->query($sql);
                // phpcs:enable WordPress.DB.PreparedSQL

                // Set the new order
                $_this->setParent(null, $newOrder);
            } else {
                // There is nothing given
                throw new Exception(__('Something went wrong.', 'real-media-library-lite'));
            }

            $this->debug('Successfully relocated', __METHOD__);
            return true;
        } catch (Exception $e) {
            $this->debug('Error: ' . $e->getMessage(), __METHOD__);
            return [$e->getMessage()];
        }
    }
}
