<?php
/**
 * Versioning Handler Class
 * MTC Media's CMS2+ Versioning Handler class responsible for handling CMS2+ data in for versioning.
 * @author Rihards Silins
 * @copyright MTC Media Ltd
 * @version 2 16/09/2016
 * @access public
 */
namespace Mtc\Cms\Handlers;

use ContentManager;
use Listing;
use Page;

class VersioningHandler
{
    /**
     * VersioningHandler::createNewPageHistoryVersion
     * Creates a new page history version
     * @param Page Object $page
     * @return Page Object $new_page_history_version
     */
    public static function createNewPageHistoryVersion($page)
    {
        $content_manager = new ContentManager();
        $requested_history_page_id = $content_manager->copyPage($page);
        $history_page = new Page();
        $history_page->get($requested_history_page_id);
        $history_page->type = "history";
        $history_page->draft_for_page_id = $page->id;
        $history_page->review_status = 0;
        $history_page->updated = $page->updated;
        $history_page->comment = "";
        $history_page->save();
        $history_page_id = $history_page->id;
        $history_page = new Page();
        $history_page->get($history_page_id); // reload
        $history_page->versions = $history_page->versions." ".$history_page->id;
        $history_page->save();
        return $history_page;
    }

    /**
     * VersioningHandler::createNewPageSandbox
     * Creates a new page sandbox
     * @param Page Object $page
     * @return Page Object $new_page_history_version
     */
    public static function createNewPageSandbox($version_page, $live_page)
    {
        $content_manager = new ContentManager();
        $preview_page_id = $content_manager->copyPage($version_page);
        $preview_page = new Page();
        if (!empty($live_page->language)) {
            $preview_page->setLanguage($live_page->language);
        }
        $preview_page->get($preview_page_id);
        $preview_page->versions = $version_page->versions;
        $preview_page->draft_for_page_id = $live_page->id;
        $preview_page->review_status = 0;
        $preview_page->updated = $version_page->updated;
        $preview_page->comment = "";
        $preview_page->save();
        return $preview_page;
    }

    /**
     * VersioningHandler::getPageLastHistoryVersion
     * Get page last history version. Which also should be the "current version"
     * @param string $page_versions
     * @return int/null $page_last_history_version
     */
    public static function getPageLastHistoryVersion($page_versions)
    {
        if (empty($page_versions)) {
            return null;
        }
        $page_versions = trim($page_versions);
        $versions = explode(" ", $page_versions);
        if (empty($versions)) {
            return null;
        }
        $page_last_history_version = $versions[(count($versions)-1)];
        if (!is_numeric($page_last_history_version)) {
            return null;
        }
        if (!Page::exists($page_last_history_version)) {
            return null;
        }
        return (int)$page_last_history_version;
    }

    /**
     * VersioningHandler::checkForAMoreRecentVersion
     * Check for a more recent version
     * @param Page Object $page
     * @return int $more_recent_version_page_id
     */
    public static function checkForAMoreRecentVersion($page)
    {
        $more_recent_version_page_id = 0;
        $lister = Listing::newInstance()
            ->setLimit(1)
            ->onlyPublished(false)
            ->onlyDefaultPages(false)
            ->setFilter([
                " `pages`.`type` = 'history' ",
                " `pages`.`draft_for_page_id` = :draft_for_page_id ",
                " `pages`.`id` NOT IN (:id_1, :id_2, :id_3) ",
                " `pages`.`updated` > :updated "
            ])
            ->setParams([
                ":draft_for_page_id"    => $page->id,
                ":id_1"                 => $page->id,
                ":id_2"                 => $page->preview_page->id,
                ":id_3"                 => $page->history_page->id,
                ":updated"              => $page->updated
            ])
            ->setOrder([
                " `pages`.`updated` DESC "
            ])
            ->run();

        $lister->getListing();

        if (count($lister->list)) {
            $more_recent_version_page_id = $lister->list[0]->id;
        }

        return $more_recent_version_page_id;
    }

    /**
     * VersioningHandler::isValidHistoryPage
     * Check if $history_page_to_check is a valid history page for $page
     * @param Page Object $history_page_to_check
     * @param Page Object $page page to whom $history_page_to_check should be a history of
     * @return bool
     */
    public static function isValidHistoryPage($history_page_to_check, $page)
    {
        if (
            !empty($history_page_to_check->id) &&
            $history_page_to_check->type == "history" &&
            $history_page_to_check->draft_for_page_id == $page->id &&
            $history_page_to_check->id != $page->id
        ) {
            return true;
        }
        return false;
    }

    /**
     * VersioningHandler::parsePageForCmPanelVersioningPageload
     * Parse Page For Versioning
     * @param Page Object $page
     * @return Page Object $page
     */
    public static function parsePageForCmPanelVersioningPageload($page, array $get_request)
    {
        $page->same_as_current_version = false;
        // This fion gets from the "default" page the latest version in it's version history
        // which should be the "current" version
        $latest_history_version_id = self::getPageLastHistoryVersion($page->versions);
        // First attempt to get history page that might have been requested
        if (!empty($get_request['history_page_id']) && is_numeric($get_request['history_page_id'])) {
            $potential_history_page = new Page();
            $potential_history_page->get($get_request['history_page_id']);
            if (self::isValidHistoryPage($potential_history_page, $page)) {
                $history_page = $potential_history_page;
            }
        }
        // If no history page yet - attempt to get latest history page according to getPageLastHistoryVersion
        if (empty($history_page) && !empty($latest_history_version_id)) {
            $potential_history_page = new Page();
            $potential_history_page->get($latest_history_version_id);
            if (self::isValidHistoryPage($potential_history_page, $page)) {
                $history_page = $potential_history_page;
            }
        }
        // If no history page yet - make one
        if (empty($history_page)) {
            $history_page = self::createNewPageHistoryVersion($page);
            $latest_history_version_id = (int)$history_page->id;
            $page->versions .= " ".$history_page->id;
            $page->save();
        }

        $page->history_page = $history_page;

        // Generate a sandbox for this page
        // This could become the next version if saved as version or used for advanced preview.
        $page->preview_page = self::createNewPageSandbox($history_page, $page);

        // check if the history version is the current version
        if ($latest_history_version_id === (int)$history_page->id) {
            $page->same_as_current_version = true;
            // more recent version disclamer
            $page->more_recent_version_page_id = self::checkForAMoreRecentVersion($page);
        }

        return $page;
    }
}
