<?php

/**
 * Created by PhpStorm.
 * User: gerd
 * Date: 29.12.16
 * Time: 09:36
 */

namespace QUI\Tour;

use QUI;
use QUI\Utils\DOM;
use QUI\Utils\Text\XML;
use QUI\Utils\Singleton;

/**
 * Class TourHandler.
 * @package QUI\Tour
 */
class TourHandler extends Singleton
{
    /**
     * @var array
     */
    protected $list = array();


    /**
     * Returns all tours in the system.
     * If a language code is given, only tours supporting this language are returned.
     *
     * @param string $languageCode - Optional: only return tours that support this language. Should be in two character form (ISO 639-1)
     *
     * @return array
     *
     * @throws QUI\Exception
     */
    public function getList($languageCode = "")
    {
        if (!empty($this->list)) {
            return $this->list;
        }

        try {
            $this->list = QUI\Cache\Manager::get('quiqqer/tour/tourhandler/list');
            return $this->list;
        } catch (QUI\Exception $Exception) {
        }

        $result   = array();
        $packages = QUI::getPackageManager()->getInstalled();

        foreach ($packages as $package) {
            $Package = QUI::getPackage($package['name']);
            $pkgName = $Package->getName();
            $tourXML = $Package->getDir() . 'tour.xml';

            if (!file_exists($tourXML)) {
                continue;
            }

            $Dom   = XML::getDomFromXml($tourXML);
            $Path  = new \DOMXPath($Dom);
            $tours = $Path->query("//quiqqer/tours/tour");

            foreach ($tours as $key => $Tour) {
                $tour = array(
                    'title'       => '',
                    'description' => '',
                    'package'     => $pkgName,
                    'steps'       => array(),
                    'languages'   => []
                );

                /* @var $Tour \DOMElement */
                $Title       = $Tour->getElementsByTagName('title');
                $Description = $Tour->getElementsByTagName('description');

                if ($Title->length) {
                    $tour['title'] = DOM::getTextFromNode($Title->item(0), false);
                }

                if ($Description->length) {
                    $tour['description'] = DOM::getTextFromNode($Description->item(0), false);
                }

                if (empty($tour['title']) || empty($tour['description'])) {
                    continue;
                }

                // steps
                $steps = $Tour->getElementsByTagName('step');

                foreach ($steps as $Step) {
                    /* @var $Step \DOMElement */
                    $tour['steps'][] = $this->parseStep($Step);
                }


                // languages
                $languages = $Tour->getElementsByTagName('language');

                foreach ($languages as $language) {
                    $tour['languages'][] = strtolower(DOM::getTextFromNode($language, false));
                }

                // If no language is explicitly set (older tour.xml files), assume english is present
                if (empty($tour['languages'])) {
                    $tour['languages'][] = 'en';
                }

                // If the tour doesn't support this language, don't return it
                if (!empty($languageCode) && !in_array(strtolower($languageCode), $tour['languages'])) {
                    continue;
                }


                // require
                if ($Tour->getAttribute('require')) {
                    $tour['require'] = $Tour->getAttribute('require');
                }


                // internal id
                if (!isset($result[$pkgName])) {
                    $tour['id'] = 0;
                } else {
                    $tour['id'] = count($result[$pkgName]);
                }

                $result[$pkgName][] = $tour;
            }
        }


        $this->list = $result;

        QUI\Cache\Manager::set('quiqqer/tour/tourhandler/list', $result);

        return $result;
    }

    /**
     * @param \DOMElement|\DOMNode $Step
     * @return array
     */
    public function parseStep(\DOMElement $Step)
    {
        $result = array(
            'title'       => '',
            'description' => ''
        );

        /* @var $Tour \DOMElement */
        $Title       = $Step->getElementsByTagName('title');
        $Description = $Step->getElementsByTagName('description');

        if ($Title->length) {
            $result['title'] = DOM::getTextFromNode($Title->item(0), false);
        }

        if ($Description->length) {
            $result['description'] = DOM::getTextFromNode($Description->item(0), false);
        }

        // optionals
        $AttachTo = $Step->getElementsByTagName('attachTo');

        if ($AttachTo->length) {
            $result['attachTo'] = array(
                'element'  => $AttachTo->item(0)->getAttribute('element'),
                'position' => $AttachTo->item(0)->getAttribute('position')
            );
        }


        $AdvanceOn = $Step->getElementsByTagName('advanceOn');

        if ($AdvanceOn->length) {
            $result['advanceOn'] = array(
                'element' => $AdvanceOn->item(0)->getAttribute('element'),
                'event'   => $AdvanceOn->item(0)->getAttribute('event')
            );
        }


        return $result;
    }

    /**
     *
     * @param QUI\Package\Package $Package
     * @param $index
     * @return array
     *
     * @throws QUI\Tour\Exception
     */
    public function getTour(QUI\Package\Package $Package, $index)
    {
        $list    = $this->getList();
        $package = $Package->getName();

        if (
            !isset($list[$package]) ||
            !isset($list[$package][$index])
        ) {
            throw new QUI\Tour\Exception('Tour not found', 404, array(
                'package' => $Package->getName(),
                'index'   => $index
            ));
        }

        return $list[$package][$index];
    }
}
