<?php
namespace Solwin\Verticalmenu\Model;

/**
 * @method Menu setMenuTitle($menuTitle)
 * @method Menu setType($type)
 * @method Menu setTitle($title)
 * @method Menu setUrl($url)
 * @method Menu setTab($tab)
 * @method Menu setCategoryId($categoryId)
 * @method Menu setIcon($icon)
 * @method Menu setSortOrder($sortOrder)
 * @method Menu setStatus($status)
 * @method mixed getMenuTitle()
 * @method mixed getType()
 * @method mixed getTitle()
 * @method mixed getUrl()
 * @method mixed getTab()
 * @method mixed getCategoryId()
 * @method mixed getIcon()
 * @method mixed getSortOrder()
 * @method mixed getStatus()
 * @method Menu setParentId(\int $parentId)
 * @method int getParentId()
 * @method Menu setPath(\string $path)
 * @method string getPath()
 * @method Menu setPosition(\int $path)
 * @method int getPosition()
 * @method Menu setChildrenCount(\int $path)
 * @method int getChildrenCount()
 * @method Menu setCreatedAt(\string $createdAt)
 * @method string getCreatedAt()
 * @method Menu setUpdatedAt(\string $updatedAt)
 * @method string getUpdatedAt()
 * @method Menu setMovedMenuId(\string $id)
 * @method Menu setAffectedMenuIds(array $ids)
 */
class Menu extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Root of the Menu tree
     * 
     * @var string
     */
    const TREE_ROOT_ID = 1;

    /**
     * Cache tag
     * 
     * @var string
     */
    const CACHE_TAG = 'solwin_verticalmenu_menu';

    /**
     * Cache tag
     * 
     * @var string
     */
    protected $_cacheTag = 'solwin_verticalmenu_menu';

    /**
     * Event prefix
     * 
     * @var string
     */
    protected $_eventPrefix = 'solwin_verticalmenu_menu';

    /**
     * Menu Factory
     * 
     * @var \Solwin\Verticalmenu\Model\MenuFactory
     */
    protected $menuFactory;

    /**
     * constructor
     * 
     * @param \Solwin\Verticalmenu\Model\MenuFactory $menuFactory
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
     * @param array $data
     */
    public function __construct(
        \Solwin\Verticalmenu\Model\MenuFactory $menuFactory,
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    )
    {
        $this->menuFactory = $menuFactory;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }


    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Solwin\Verticalmenu\Model\ResourceModel\Menu');
    }

    /**
     * Get identities
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }

    /**
     * get entity default values
     *
     * @return array
     */
    public function getDefaultValues()
    {
        $values = [];

        return $values;
    }

    /**
     * get tree path ids
     *
     * @return array
     */
    public function getPathIds()
    {
        $ids = $this->getData('path_ids');
        if ($ids === null) {
            $ids = explode('/', $this->getPath());
            $this->setData('path_ids', $ids);
        }
        return $ids;
    }

    /**
     * get all parent ids
     * 
     * @return array
     */
    public function getParentIds()
    {
        return array_diff($this->getPathIds(), [$this->getId()]);
    }

    /**
     * move Menu in tree
     * 
     * @param $parentId
     * @param $afterMenuId
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Exception
     */
    public function move($parentId, $afterMenuId)
    {
        try {
            $parent = $this->menuFactory->create()->load($parentId);
        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Sorry, but we can\'t move the Menu because we can\'t find the new parent Menu you selected.'),
                $e
            );
        }

        if (!$this->getId()) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Sorry, but we can\'t move the Menu because we can\'t find the new parent Menu you selected.')
            );
        } elseif ($parent->getId() == $this->getId()) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __(
                    'We can\'t perform this Menu move operation because the parent Menu matches the child Menu.'
                )
            );
        }

        $this->setMovedMenuId($this->getId());
        $oldParentId = $this->getParentId();
        $oldParentIds = $this->getParentIds();

        $eventParams = [
            $this->_eventObject => $this,
            'parent' => $parent,
            'menu_id' => $this->getId(),
            'prev_parent_id' => $oldParentId,
            'parent_id' => $parentId,
        ];

        $this->_getResource()->beginTransaction();
        try {
            $this->_eventManager->dispatch($this->_eventPrefix . '_move_before', $eventParams);
            $this->getResource()->changeParent($this, $parent, $afterMenuId);
            $this->_eventManager->dispatch($this->_eventPrefix . '_move_after', $eventParams);
            $this->_getResource()->commit();

            // Set data for indexer
            $this->setAffectedMenuIds([$this->getId(), $oldParentId, $parentId]);
        } catch (\Exception $e) {
            $this->_getResource()->rollBack();
            throw $e;
        }
        $this->_eventManager->dispatch($this->_eventPrefix . '_move', $eventParams);
        $this->_cacheManager->clean([self::CACHE_TAG]);

        return $this;
    }
}
