<?php

declare(strict_types=1);

namespace FiloBlu\ExtBlackbirdMenuManager\Model\Menu;


use Blackbird\MenuManager\Api\Data\MenuInterface;
use Blackbird\MenuManager\Api\Data\NodeInterface;
use Blackbird\MenuManager\Api\MenuRepositoryInterface;
use Blackbird\MenuManager\Api\NodeRepositoryInterface;
use Blackbird\MenuManager\Model\Menu\NodeFactory;
use Blackbird\MenuManager\Model\MenuFactory;
use Magento\Framework\Serialize\SerializerInterface;

/**
 *
 */
class Importer implements ImporterInterface
{
    /**
     * @var \Magento\Framework\Serialize\SerializerInterface
     */
    private $serializer;
    /**
     * @var \Blackbird\MenuManager\Model\MenuFactory
     */
    private $menuFactory;
    /**
     * @var \Blackbird\MenuManager\Api\MenuRepositoryInterface
     */
    private $menuRepository;
    /**
     * @var \Blackbird\MenuManager\Api\NodeRepositoryInterface
     */
    private $nodeRepository;
    /**
     * @var \Blackbird\MenuManager\Model\Menu\NodeFactory
     */
    private $nodeFactory;

    /**
     * @param \Blackbird\MenuManager\Model\MenuFactory $menuFactory
     * @param \Blackbird\MenuManager\Api\MenuRepositoryInterface $menuRepository
     * @param \Blackbird\MenuManager\Api\NodeRepositoryInterface $nodeRepository
     * @param \Blackbird\MenuManager\Model\Menu\NodeFactory $nodeFactory
     * @param \Magento\Framework\Serialize\SerializerInterface $serializer
     */
    public function __construct(
        MenuFactory $menuFactory,
        MenuRepositoryInterface $menuRepository,
        NodeRepositoryInterface $nodeRepository,
        NodeFactory $nodeFactory,
        SerializerInterface $serializer
    ) {
        $this->serializer = $serializer;
        $this->menuFactory = $menuFactory;
        $this->menuRepository = $menuRepository;
        $this->nodeRepository = $nodeRepository;
        $this->nodeFactory = $nodeFactory;
    }

    /**
     * @param string $data
     * @return void
     */
    public function import(string $data)
    {
        $menus = $this->serializer->unserialize($data);

        foreach ($menus as $menuData)
        {
            $this->createMenu($menuData);
        }
    }


    /**
     * @param array $data Array containing menu information like 'title', 'identifier', 'menu_status', and 'stores'
     */
    public function createMenu(array $data)
    {
        $menu = $this->menuFactory->create();
        $menu->setTitle($data['data']['title']);
        $menu->setIdentifier($data['data']['identifier']);
        $menu->setIsActive($data['data']['is_active']);
        $menu->setStoreViews($data['stores']);
        $menu->setCreationTime($data['data']['creation_time']);
        $menu->setUpdateTime($data['data']['update_time']);
        $menu->setCustomerGroup($data['data']['customer_group']);
        $menuObject = $this->menuRepository->save($menu);
        $this->createNodes($menuObject, $data['nodes']);
    }

    /**
     * @param \Blackbird\MenuManager\Model\Menu |\Blackbird\MenuManager\Api\Data\MenuInterface $menu
     * @return void
     */
    public function createNodes(MenuInterface $menu, array $nodes, NodeInterface $parent = null)
    {
        foreach ($nodes as $node)
        {
            $nodeObject = $this->createNode($menu, $node, $parent);
            $this->createNodes($menu, $node['nodes'], $nodeObject);
        }
    }

    /**
     * @param \Blackbird\MenuManager\Model\Menu |\Blackbird\MenuManager\Api\Data\MenuInterface $menu
     * @param array $data
     * @param \Blackbird\MenuManager\Model\Menu\Node| \Blackbird\MenuManager\Api\Data\NodeInterface $parent
     * @return void
     */
    public function createNode(MenuInterface $menu, array $data, NodeInterface $parent = null)
    {
        $nodeObject = $this->nodeFactory->create();
        $nodeObject->setMenuId($menu->getId());
        $nodeObject->setParentId(null);
        $nodeObject->setTitle($data['title']);
        $nodeObject->setLevel($data['level']);
        $nodeObject->setPosition($data['position']);
        $nodeObject->setType($data['type']);

        if ($parent !== null)
        {
            $nodeObject->setParentId($parent->getId());
        }

        foreach ($this->getPropertiesToCopy() as $property)
        {
            if (!isset($data[$property]))
            {
                continue;
            }

            $nodeObject->setData($property, $data[$property]);
        }

        return $this->nodeRepository->save($nodeObject);
    }

    /**
     * @return string[]
     */
    public function getPropertiesToCopy(): array
    {
        return [
            'classes',
            'link_first_child',
            'canonical',
            'inline_css',
            'url_path',
            'entity_id',
            'target',
            'status'
        ];
    }

}