<?php

namespace common\modules\pages\services;

use common\modules\pages\helpers\PageHelper;
use common\modules\pages\entities\Page;
use common\modules\pages\forms\PageForm;
use common\modules\pages\repositories\PageRepository;
use yii\db\ActiveRecord;

class PageManageService
{
    private $pages;

    public function __construct(PageRepository $pages)
    {
        $this->pages = $pages;
    }

    public function create(PageForm $form, $type = Page::TYPE_PUBLIC): Page
    {
        $parent = $this->pages->get($form->parentId);
        $page = Page::create(
        	$form,
            $form->slug,
	        $type
        );
        if ($type == Page::TYPE_PUBLIC) {
	        $page->appendTo( $parent );
        }
        else {
        	$parent = Page::find()->andWhere(['tree' => 2])->andWhere(['depth' => 0])->one();
	        $page->appendTo( $parent );
        }
        $this->pages->save($page);
        return $page;
    }

    public function edit($id, PageForm $form, $type = Page::TYPE_PUBLIC): void
    {
        $page = $this->pages->get($id);

	    PageHelper::saveRevision($page);

        $this->assertIsNotRoot($page);
        $page->edit(
        	$form,
            $form->slug,
            $type
        );
        if ($form->parentId !== $page->parent->id) {
            $parent = $this->pages->get($form->parentId);
            $page->appendTo($parent);
        }
        $this->pages->save($page);
    }

    public function moveUp($id): void
    {
        $page = $this->pages->get($id);
        $this->assertIsNotRoot($page);
        if ($prev = $page->prev) {
            $page->insertBefore($prev);
        }
        $this->pages->save($page);
    }

    public function moveDown($id): void
    {
        $page = $this->pages->get($id);
        $this->assertIsNotRoot($page);
        if ($next = $page->next) {
            $page->insertAfter($next);
        }
        $this->pages->save($page);
    }

    public function remove($id): void
    {
        $page = $this->pages->get($id);

        // Remove revisions
	    $this->clearHistory($page);

        $this->assertIsNotRoot($page);
        $this->pages->remove($page);
    }

    private function assertIsNotRoot(Page $page): void
    {
        if ($page->isRoot()) {
            throw new \DomainException('Unable to manage the root page.');
        }
    }

	public function removePreviews(): void
	{
		$pages = Page::find()->andWhere(['type' => Page::TYPE_PREVIEW])->all();
		foreach ($pages as $page) {
			$page->delete();
		}
	}

	public function clearHistory(Page $page): void
	{
		Page::deleteAll(['revision_id' => $page->id]);
	}

	public function restoreHistory($from_id, $id): void
	{
		$page = $this->pages->get($id);
		$from = $this->pages->get($from_id);

		$page->slug = $from->slug;
		$page->created_at = $from->created_at;
		$page->updated_at = $from->updated_at;
		$page->revision_at = $from->revision_at;

		$this->pages->save($page);

		// remove distance translation
		foreach ( $page->translations as $translate ) {
			/* @var $translate ActiveRecord */
			$translate->delete();
		}
		// move source translation
		foreach ( $from->translations as $translate ) {
			/* @var $translate ActiveRecord */
			$translate->page_id = $page->id;
			$translate->save();
		}
		// remove current revision
		$this->pages->remove($from);
		Page::deleteAll(['AND', ['revision_id' => $page->id], ['>', 'revision_at', $page->revision_at]]);
	}
}